2

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 as const, which can only be placed after the * in a declaration.
  • All pointers obtained by & operator is __nonnull.
  • A __nonnull pointer value or const reference can be automatically converted to a normal pointer, but not vice-versa without a cast. (T *__nonnull can be converted to T *, and T *__nonnull & can be converted to T *const &)
  • Writable references of pointers cannot be automatically converted between normal and __nonnull (T *__nonnull & CANNOT be converted to T *&), 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 really NULL, the behaviour is undefined.

  • Assigning a null-pointer constant 0, NULL and nullptr 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 on NULL.
  • 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
    Did you look at not_null in the gsl library? Here is one article about it: visualstudiomagazine.com/articles/2016/06/01/… – Brandin Jan 6 '17 at 7:40
  • 4
    References already are non null pointers, with the restriction that you may not reassign them. Most of your suggested behaviours can be implemented with a nonnull<T*> wrapper, no language changes required. – amon Jan 6 '17 at 8:00
  • The question would be "is there a good reason for a NULL-safe type system?" - NULL is there for a good reason. – tofro Jan 6 '17 at 12:10
  • 1
    This question would be handled better on the ISO-C++ proposal forum. Q&A is not an effective means for tempering a proposal. – Nicol Bolas Jan 6 '17 at 15:00
  • 2
    @tofro And that good reason is? I can't think of any advantages null has over a proper option type. – CodesInChaos Jan 6 '17 at 18:30
2

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 Jan 7 '17 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>. Whereas gsl::not_null<shared_ptr<T>> works (though not unique_ptr). – Nicol Bolas Jan 7 '17 at 16:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.