The following code prints nullptr instead of empty (godbolt link):
#include <iostream>
class empty { };
#if 1
void f(std::nullptr_t) {
std::cout << "nullptr\n";
}
#endif
void f(empty) {
std::cout << "empty\n";
}
int main() {
f({});
}
Disabling the f(nullptr_t) variant causes empty to be printed. What are the rules C++ is using to select the nullptr_t variant over the empty variant when both are available?
Initializing
std::nullptr_t(or any other fundamental type) with{}is better because it result in an identity conversion, whereas initializing class types results in a user-defined conversion sequence:- [over.ics.list] p8
emptyis an aggregate type, so this paragraph applies.std::nullptr_tis not a class, so the following paragraph applies:- [over.ics.list] p10
[over.best.ics] explains which implicit conversion sequence is better, but it should be obvious that an identity conversion beats everything else.