On Tue, Apr 2, 2019 at 4:33 PM Gavin Lambert via Boost < boost@lists.boost.org> wrote:
There is always potential uncertainty about the actual content type of a variant, requiring either assumptions (and UB or exceptions if wrong) or explicitly testing, eg. with visit
I read the above as "UB or error handling if wrong". It does not matter what form of error handling is used. The use of "assumption" is imprecise, because the assumptions we're talking about are a matter of a conscious design choice. If we're assuming that the basic invariants are in place during error recovery (the basic guarantee), it is because we are writing code to ensure that it is true. Of course the point of it is to avoid having to explicitly test. The problem with explicitly testing is that it must be done everywhere because we don't know if maybe we are being called from an error-handling context (note, this doesn't necessarily mean exception handling). For example, every member function must check if the class invariants are in place for *this (assuming UB is not acceptable).
Checking if a variant is empty seems no different to me than checking if it contains an int; eliding either check confers exactly the same risks.
Under the basic guarantee, you'd only check if it contains an int if you care whether it contains an int. Typical use is not to check, but to do something if it contains an int and something else if it contains a different type. There is no check.
Unexpectedly changing type and/or content is exactly as bad as unexpectedly becoming empty.
It is not as bad. Introducing the empty state forces us to define behavior for that state. This is logically equivalent to requiring well defined behavior from any member function even for instances that failed to initialize. It's better to ensure and then assume that this can not happen.