nullptr_t is the type for nullptr. When I use nullptr_t, I have to use the header file <cstddef> but why isn't it required when using the nullptr keyword alone?
nullptr_t is the type for nullptr. When I use nullptr_t, I have to use the header file <cstddef> but why isn't it required when using the nullptr keyword alone?
As per [lex.key]/1, nullptr is a keyword:
The identifiers shown in Table 5 are reserved for use as keywords (that is, they are unconditionally treated as keywords in phase 7) [...]
[tab:lex.key]: ...
nullptr
Whereas std::nullptr_t is an alias declaration defined by the standard. Particularly, as of [cstddef.syn], is is defined as the type of the a nullptr expression:
Header
<cstddef>synopsis...
using nullptr_t = decltype(nullptr);
as specified in [support.types.nullptr]/1:
The type
nullptr_tis a synonym for the type of anullptrexpression, and it has the characteristics described in [basic.fundamental] and [conv.ptr].
Thus, to make use of std::nullptr_t, you need to include the <cstddef> header, but you can likewise use decltype(nullptr) if you simply want the same underlying type but without using the std::nullptr_t alias.
nullptr is a keyword, std::nullptr_t is a type defined by the C++ Stadnard library. Keywords are not introduced by header files, they are "wired" in the compiler itself.
Most types defined by C++ are defined via the standard library. Only a handful — char, int … — are defined via keywords, and they are all old (i.e. they have been part of C++ since the beginning). Other types (std::byte, std::initializer_list, …) are not. There are many reasons for this, but mainly it just isn’t necessary to define new keywords, and defining new keywords is intrusive and breaks existing code that uses the same identifier, so it’s avoided when possible.
The real question therefore is: why did C++ define a keyword for nullptr? The original proposal explicitly lists this as a design goal. It gives the following reasons, amongst others:
nullptr value via C++ code in a header is challenging to make it work correctly in constant expressions. I believe that this point is no longer relevant since probably C++17, but it was definitely a concern in C++11, when the proposal was introduced.Reason (1) on its own might not seem compelling, since the same reason would apply to the type name nullptr_t. But in actual usage, nullptr is a lot more common; code rarely needs to name the null pointer type.
Taken together, these are strong reasons to make the null pointer value constant a built-in keyword. But, as noted, the reasons for making the type name also keyword aren’t nearly as strong.