sob., 2 mar 2019 o 15:50 Peter Dimov via Boost
Andrzej Krzemienski wrote:
For instance, the variant's move assignment will sometimes use T's move assignment rather than move constructor when changing the variant's type, as in the following example:
Interesting.
Since the destructors and the move assignments are trivial, this variant has a pseudo-trivial move constructor, that is, it does the equivalent of memcpy.
This however doesn't quite match the specification.
I need to look into the latest changes to std::variant to see how it handles triviality in this case.
Describe the algorithm for achieving the [strong] guarantee.
It so happens that the strong guarantee is unachievable with variant (without too much double buffering.) You can either have basic, or noexcept.
If all contained types have noexcept move constructors and noexcept move assignments, the move assignment of variant is noexcept.
If all types have noexcept move constructors but not all have noexcept move assignments (this can be the case for f.ex. std::vector with a not-always-equal allocator), variant's move assignment is only as strong as the move assignments of the contained types, but emplace is noexcept.
If not all types have noexcept move constructors, I don't know of a good way to achieve the strong guarantee.
Technically, it could be possible with unconditional double buffering, but I guess the cost is not worth it. My point is, users who will read the introductory part of the documentation will get an incorrect impression that variant2 already offers a strong exception safety guarantee. The docs never state that, but when you read the clever things what this library does, some users will think, "surely this must be to achieve the strong guarantee". A not that states explicitly that this is not a strong guarantee would help avoid this confusion. Regards, Andrzej