On 2/06/2017 00:15, Peter Dimov wrote:
That's what I was thinking - that you want to place an assert there - I just wanted to confirm that this is the only objection. Do we agree that returning nullptr from operator-> is good for informing the static analyzer and the optimizer that a value is present?
I assume you meant "not present" there. Having an explicit assert is still probably better than just returning nullptr and hoping for a static analyzer to pick up on that (or to crash at runtime). There are some platforms where unfortunately addresses around zero are valid (and while the standards allow the compiler to make nullptr not zero in this case, I don't know of any compilers that actually do so, probably because it's hard to actually do that alongside code that assumes it can memset(0) to get null pointers). I think the assert should be in there regardless; so then the question becomes whether you just reinterpret_cast<> after that or if you check type and return nullptr if you somehow survive the assert. It's not even really a narrow vs. wide contract thing, because it's never well-defined behaviour for -> to return nullptr. If assertions are disabled then both of these behaviours are UB (since returning nullptr from -> will result in dereferencing nullptr, which is inherently UB), but the second one is at least more likely to crash on those platforms that don't have valid memory around 0, and that's a good thing. On the other hand, some people would argue that the extra branch is pointless, especially in contexts where you check up front once and then use -> multiple times, which is not an uncommon pattern. (Sure, you could use * once and capture a reference, then avoid the issue entirely, but that can make the code look more awkward.)