gsl::not_null vs. std::reference_wrapper vs. T&

References are not pointers that cannot be null. References are semantically very different to pointers.

References have value assignment and comparison semantics; that is, assignment or comparison operations involving references read and write the referenced value. Pointers have (counterintuitively) reference assignment and comparison semantics; that is, assignment or comparison operations involving pointers read and write the reference itself (i.e. the address of the referenced object).

As you noted, references cannot be rebound (due to their value assignment semantics), but the reference_wrapper<T> class template can be rebound, because it has reference assignment semantics. This is because reference_wrapper<T> is designed to be used with STL containers and algorithms, and would not behave correctly if its copy assignment operator didn’t do the same thing as its copy constructor. However, reference_wrapper<T> still has value comparison semantics, like a reference, so it behaves very differently to pointers when used with STL containers and algorithms. For example, set<T*> can contain pointers to different objects with the same value, while set<reference_wrapper<T>> can contain a reference to only one object with a given value.

The not_null<T*> class template has reference assignment and comparison semantics, like a pointer; it is a pointer-like type. This means that it behaves like a pointer when used with STL containers and algorithms. It just can’t be null.

So, you are right in your assessment, except you forgot about comparison semantics. And no, reference_wrapper<T> will not be made obsolete by any kind of pointer-like type, because it has reference-like value comparison semantics.

Leave a Comment