In today's post, I like to show you the benefit of a often unknown type: std::nullptr_t.
You have that data type in the language since C++11, together with the much more frequently used nullptr. While nullptr is the value, std::nullptr_t is the data type that can hold exactly this value.
The current situation
Where is std::nullptr_t helpful? Let's take a look at std::string. Creating a std::string object from a nullptr is undefined behavior. Yet, it happens. That's why probably all the standard libraries nowadays have an assertion to check for that.
A down-stripped version looks like the following:
1 2 3 4 5 6 7 8 9 10 | |
You have two ways of creating a std::string object:
1 2 3 4 | |
In A, I create a std::string object with the constant nullptr and the data type std::nullptr_t. While in C, the case is slightly different. The const char* points to a nullptr which could come from a run-time function.
To be clear, the assert check in the string constructor, for C, will not go away as long as you want to protect your users from creating a std::string object at run-time.
Improving the situation
Still, you can improve the compile-time checkability, catching as many instances as possible at compile-time, like A. By adding a deleted constructor for std::nullptr_t you catch all the instances of A above. The string class then looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
With the help of C++26 delete can have a message enabling you to leave breadcrumbs stating why the constructor is deleted.
In C++23 both std::string and std::string_view have a deleted constructor from std::nullptr_t to catch these situations at compile-time.
Andreas

Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.