On 3/04/2019 05:27, Andrzej Krzemienski wrote:
This is not a full review yet. I just wanted to discuss the design first, especially the never-empty guarantee. And I am going to rehash the old argument.
The core of variant2 is its never-empty guarantee and the mechanism to achieve it: a number of different algorithms chosen depending on what the potentially stored types permit. In fact this mechanism is not much different than the one present in boost::variant.
I agree with most of the points that Andrzej has made, although I would go a step further and question why people want a never-empty variant in the first place. 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. 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. Requiring that variants always possess an empty state dramatically simplifies implementation, including default construction and move assignment. And it avoids the valueless_by_exception kludge by promoting it to an entirely expected possible state of variant. (Thereby increasing the chance that consumers will consider it.) It also means that (like traditional monads), variant<T> is behaviorally equivalent (bar some naming conventions) to optional<T>, which seems like a consistent conceptual choice. And variant<> is valid and can only hold the empty state. Furthermore, while I can see possible value in a never-empty strong-guarantee variant (although I remain unconvinced that the "never-empty" part provides much benefit, as above); as soon as this guarantee is weakened then I don't see any advantage at all in trying to maintain a "never-empty" property. Unexpectedly changing type and/or content is exactly as bad as unexpectedly becoming empty.