On Sat, Oct 5, 2013 at 7:09 AM, Daniel James
Preprocessor switches tend to cause more problems than they solve. For a relevant example, see https://svn.boost.org/trac/boost/ticket/7028 There's confusion about what the switches do, there's inconsistencies in what they do, there are subtle issues in implementing them in a consistent manner, and to top it all, it still hasn't been resolved.
I'd rather just an assert. I only mention the switch possibility as a compromise to appease both sides.
but ultimately this is an
error that cannot be handled once such a condition is reached. You cannot reliably continue.
I've already given a counter-example to that. If your data is well encapsulated, an unexpected null is not an indicator of a problem in the global state.
I apologize, but can you repeat your example? Skimming back, I do not see it.
it's a precondition violation, which is UB, so just use an assertion given that this particular precondition is easily able to be checked. Further, I vote against removing it as a precondition/turning it into documented exception-on-null
This class is meant to make code safer - that is its point. But as you describe it, just using this class introduces the possibility of undefined behaviour where there was none before. And undefined behaviour can do anything. So it actually makes code less safe. So why use the class?
It doesn't introduce UB where there was none before, it properly brings a hypothetical source of UB to initialization as opposed to dereferencing and guarantees that when you have a constructed non-null shared_ptr, you can always safely dereference it. Saying that it somehow makes code less safe is ludicrous. It makes preconditions for functions dealing with non-null shared_ptrs simpler (since the non-nullness is already guaranteed by the invariants), and also simplifies code dealing with them.
since this either A) throws an exception that cannot be
properly handled
You keep saying that, but you never justify it. This kind of thing is very contextual, there are no universal laws.
I didn't think it needed explanation: If you are using a non-null shared_ptr it is because you always want the pointer to refer to an object. Therefore, if a user attempts to construct the non-null shared_ptr with a null pointer, it is a programmer error. In other words, the programmer mistakenly believes that he is passing the function a pointer that is not null. Given that the programmer thought he was passing a valid pointer, how can he now possibly handle the exception that pops out of the function? The handler can't fix the mistake in the programmer's code.
or B) invites users to rely on the exception behavior to
use the exception for control flow (I.E. instead of checking for null before handing it off, they pass it off and check for null by catching an exception, which is a misuse of exceptions).
You have faith that programmers won't violate your pre-conditions, but you don't have faith in them following your theories about exceptions. Which is odd since the latter is easier to do, and less problematic if it isn't followed.
Exactly what theory are you referring to? That exceptions shouldn't be used as a means of basic control flow? I'd hope that we're beyond that. I present B as simply the alternative to A in the case that the function throws on null. It's just an enumeration of possibilities. If passing the null pointer was not a programmer error as describe in A, in other words, if it was an accepted possibility that the pointer might be null on the part of the programmer, then he is simply relying on the function to do the check and throw an exception. If this is the case, then the exception is no longer an exceptional case and he is instead using the exception for basic control flow. -- -Matt Calabrese