NULL
is the billion-dollar mistake but there is nothing in the type system of C++ to prevent it. However, C++ already has const-correctness so implementing NULL
-correctness seems trivial:
- introduce a keyword,
__nonnull
, as a specifier in the same class asconst
, which can only be placed after the*
in a declaration. - All pointers obtained by
&
operator is__nonnull
. - A
__nonnull
pointer value orconst
reference can be automatically converted to a normal pointer, but not vice-versa without a cast. (T *__nonnull
can be converted toT *
, andT *__nonnull &
can be converted toT *const &
) Writable references of pointers cannot be automatically converted between normal and
__nonnull
(T *__nonnull &
CANNOT be converted toT *&
), i.e.int x; int *__nonnull p = &x; int *q = p; // OK int *const &r = p; // OK int *const *s = &p; // OK int *&t = p; // ERROR, don't want to assign NULL to t int **u = &p; // ERROR, don't want to assign NULL to *u
const_cast
can be used to cast a normal pointer to a__nonnull
pointer, in which if the pointer is reallyNULL
, the behaviour is undefined.- Assigning a null-pointer constant
0
,NULL
andnullptr
to a__nonnull
pointer variable is an error. __nonnull
pointers cannot be default initialised, like a reference.- Have a standard library function to convert a normal pointer to a
__nonnull
pointer, which throws an exception onNULL
. - An optional warning will be given by compiler for dereferencing normal pointers without
NULL
check, which the practice is going to be deprecated.
Is the above proposal viable? Are the above things enough for a NULL
-safe type system?
1 Answer 1
Is the above proposal viable?
No.
First, it doesn't work for user-defined types. Whereas const
does. Even volatile
does. And with lots of smart pointer types, having it work with user-defined types is kind of important.
Second, using const_cast
to convert to __notnull
is... silly.
Third, C++ is not C. If something is important enough to get a keyword in C++, then it's important enough to get a keyword that doesn't look terrible.
Fourth, this can be done adequately through a simple type. The C++ core guidelines support library provides not_null
, which essentially has the properties you suggest. And, unlike __notnull
, it works with user-defined smart pointers too (though not unique_ptr
).
-
I don't understand why it doesn't work for user-defined types. The mechanism does not matter what type the pointer points to.Michael Tsang– Michael Tsang01/07/2017 16:36:44Commented Jan 7, 2017 at 16:36
-
@MichaelTsang: Not pointers to user-defined types. User-defined types that act like pointers:
shared_ptr
,unique_ptr
, etc. Your mechanism does not allow me to declare__notnull shared_ptr<T>
. Whereasgsl::not_null<shared_ptr<T>>
works (though notunique_ptr
).Nicol Bolas– Nicol Bolas01/07/2017 16:47:08Commented Jan 7, 2017 at 16:47 -
Pointer-like user-defined types are already awkward and badly-supported by the language though. They don't work with return value covariance, yet are often evangelized as if they were a drop-in replacement for pointers. The language should add better support for those types to be a true drop-in replacement, and while it's at it, implement some kind of nonnull keyword or attribute that can also work with those types. Better than to use the awkwardness of those types to shut down even more proposals. By the way, gsl::not_null isn't that fun to use in templates and is not taking off.Gabriel Morin– Gabriel Morin03/27/2025 00:20:05Commented Mar 27 at 0:20
nonnull<T*>
wrapper, no language changes required.null
has over a proper option type.