More compile-time checks with std::nullptr_t

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
class string {
  // data members

public:
  string(const char* str)
  {
    assert(nullptr != str);
    // ...
  }
};

You have two ways of creating a std::string object:

1
2
3
4
string berry{nullptr};  A 

const char* data{nullptr};  B 
string      cherry{data};   C 

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.

Book an in-house C++ training class

Do you like this content?

Here is your next chance joining my class:
  • Modern C++: When Efficiency Matters @CppCon
  • September 09 - 11, 2026, - UTC
Book your seat now!

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
class string {
  // data members

public:
  string(const char* str)
  {
    assert(nullptr != str);
    // ...
  }

  string(std::nullptr_t) =
    delete("Construction from nullptr is not allowed");
};

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

Recent posts