Andrzej Krzemienski 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.
It is not _the only_ objection. I thought that this one would be the easiest to communicate across.
What are the others?
In code reviews, when I see someone using the function out of contract, I know that this someone has a bug.
But this doesn't apply here, does it? When you see r->x for !r, you do know that someone has a bug, right?
vector::operator[] accesses occur in tight inner loops, the check is hard to optimize out, so we swallow the UB. Doesn't mean we have to like it, it's a necessary evil here.
Should I read the above as saying that in case of vector it would cause too much potential run-time overhead;
Not merely potential. Actual slowdown on the order of 100. You should read it as "as much as we'd like to define the behavior of operator[], doing so would be prohibitively expensive, so we won't."
The root of our disagreement is the idea that undefined behavior is good because it supposedly allows you to do this or that.
It is not in this that I see the root of our disagreement. In fact, I do not yet see where this root is. What I fight for is not an UB but narrow contracts.
Traditionally the two are synonyms in C++. If you have a narrow contract, the behavior on contract violation is undefined. Can't have one without the other.
Maybe this calls for a new kind of precondition specification: that calling a function in given circumstances is formally incorrect (tools are allowed to make use of this information), but the component still guarantees a rescue action.
That's kind of what we all want, but there's at present no way of getting there. Ideally -- let's assume we don't want to allow uses of the form `r.operator->()` -- we would want `operator->` when `!r` to either invoke a precondition violation handler that is guaranteed to terminate the program and never return, or to return `nullptr`. We have no tradition in expressing the above, so within the current vocabulary I prefer guaranteeing the `nullptr` instead of leaving the behavior undefined in the hope that it will end up being defined to the above. (It won't be.)