Why is the decltype(nullptr) an unnamed type?

436 Views Asked by At

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.

2

There are 2 best solutions below

0
Nelfeal On BEST ANSWER

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
}
0
user12002570 On

Why is std::nullptr_t an alias to an unnamed type instead of just being a built in type like int or char?

This is CWG 2689 and std::nullptr_t is considered to be a fundamental type(aka built in type), at least that seems to be the intention . This can be seen from basic.fundamental and cwg 2689:

A type denoted by cv std::nullptr_t is a distinct type. A value of type std::nullptr_t is a null pointer constant (7.3.12 [conv.ptr]). Such values participate in the pointer and the pointer-to-member conversions (7.3.12 [conv.ptr], 7.3.13 [conv.mem]). sizeof(std::nullptr_t) shall be equal to sizeof(void*).

The types described in this subclause are called fundamental types. [Note 11: Even if the implementation defines two or more fundamental types to have the same value representation, they are nevertheless different types. —end note]


Additionally, the same can be seen from type's documentation:

The C++ type system consists of the following types:

  • fundamental types
    • the type void
    • the type std::nullptr_t
    • ...

(emphasis mine)

As also mentioned on the above quoted clause from cppreference, std::nullptr_t is a fundamental type(aka built in type).