On Thu, Oct 3, 2013 at 7:23 AM, Thorsten Ottosen < thorsten.ottosen@dezide.com> wrote:
If I see a class called non_null_ptr, I pretty much expect it not to be null (it's an /invariant/), and use it assuming this.
Yes, of course, that's the whole point. Using an assert does not change that. Again, you assert preconditions. When you define preconditions for a function, it's the caller's responsibility to meet those preconditions, which is why you assert them rather than handle them (sometimes it's not even possible to really check the precondition).
How many other classes allow you to construct an illegal object (an object where the invariant is broken?). I can't give any example from Boost or the standard library.
Whenever you violate any precondition of any function you are potentially putting your program in an unreliable state, including the breaking of invariants of that object or others (this is true of Boost and the STL and other libraries). It's pretty easy to come up with examples -- again, any function with specified preconditions can do potentially this. If your function always handles checking of the precondition and doesn't break the invariants of the object when the function exits and this is documented as a reliable part of the function, then it's simply not a precondition, but rather, it's an accepted argument to the function with well-defined results. We are not making up these rules here. This is sort of the point of preconditions. For a more detailed explanation, you can reference Alexandrescu's post at http://akrzemi1.wordpress.com/2013/01/04/preconditions-part-i/ under the heading: "What if a precondition is violated?" The point is, even if you happen to throw in a particular implementation, if the precondition is such that the constructor cannot take a null pointer, then the throwing behavior is never to be relied upon by the user anyway. It's still just undefined behavior. Asserting accomplishes this, allows your function to be noexcept, and does not open the door to people [incorrectly] handling the exception (any handling of such an exception doesn't get you out of UB-land since you've broken the precondition). You have to keep in mind that when the exception is thrown, you've already told the user that the program is in an ill-defined state anyway by way of the precondition, so catching the exception is effectively meaningless. If you want unraveling of the stack or catching of the exception to be worthwhile, then you need to eliminate the precondition altogether. -- -Matt Calabrese