std::nullptr_t
is an alias for decltype(nullptr)
. The actual type of nullptr
is unnamed. Why is std::nullptr_t
an alias to an unnamed type instead of just being a built in type like int
or char
? That is like having the type int
be unnamed and std::int_t
being an alias to to decltype(1)
.
EDIT: This question is not a duplicate for this question, because that question was asking where std::nullptr_t
was in the std
namespace, and assumed that nullptr_t
was a built in type which it is not. This question is simply asking why std::nullptr_t
is an alias.
CodePudding user response:
std::nullptr_t
is its own type so that it may be implicitly converted to any pointer and pointer to member type. It cannot be a built-in type like int
or even void*
because it is an actual type, so nullptr
is not a macro (unlike NULL
) and int
or void*
are not implicitly convertible to other pointer types.
It is technically not named (though I'd say std::nullptr_t
is its name) because it doesn't need to be named, and reserving another keyword like int
or char
just for that would potentially break existing code. Introducing new keywords is never easy.
Example:
static constexpr void* VOID_NULL = 0;
static constexpr int INT_NULL = 0;
int main() {
char* char_ptr = VOID_NULL; // invalid conversion
int* int_ptr = INT_NULL; // invalid conversion
}
It was introduced to fix some issues with the NULL
macro. Mainly for type safety.
One issue with NULL
is ambiguous calls to overloads:
void f(int*) {}
void f(std::nullptr_t) {}
int main() {
f(NULL); // ambiguous call
f(nullptr); // fine, calls the std::nullptr_t overload
}
Another issue is auto type deduction:
void f(int*) {}
int main() {
auto cloned_nullptr = nullptr;
auto cloned_NULL = NULL;
f(cloned_nullptr); // fine
f(cloned_NULL); // invalid conversion
// cloned_NULL is actually long int or similar, but not a pointer type
}