Gottlob Frege wrote:
For variant<int, short>, can I assign a T that has an operator int()? Is assignment templatized?
What happens with
struct Bad { operator int() { throw false; } };
variant<int, short> v = (short)10; v = Bad();
For the following: #include "boost/variant2/variant.hpp" #include <iostream> struct Bad { operator int() { throw false; } }; using namespace boost::variant2; int main() { variant<int, short> v = (short)10; try { v = Bad(); } catch(...) { std::cout << "Exception\n"; } visit([](auto const& x){ std::cout << "(" << typeid(x).name() << ")" << x << std::endl; }, v ); } the output is Exception (short)10 There are a number of subtleties here that I haven't quite captured in the documentation; I'll see how I can document the behavior properly. The assignment itself is "template<class U> constexpr variant& operator=( U&& u ) noexcept( /*see below*/ ); Let Tj be a type that is determined as follows: build an imaginary function FUN(Ti) for each alternative type Ti. The overload FUN(Tj) selected by overload resolution for the expression FUN(std::forward<U>(u)) defines the alternative Tj which is the type of the contained value after construction. Effects: If index() == j, assigns std::forward<U>(u) to the value contained in *this. Otherwise, equivalent to emplace<j>(std::forward<U>(u))." and that's correct. So in this case index() is not j and it does emplace<1>( Bad() ). The behavior of emplace varies depending on a number of things: - whether all types are trivially destructible - whether the variant is single- or double-buffered - whether the type we're constructing is nothrow constructible from the arguments - whether all contained types are trivially move constructible and move assignable - and finally, whether, in the single buffered case, we have a monostate type In this specific case, it's trivially destructible, single buffered, int not nothrow constructible from Bar, all types trivially move constructible and move assignable; so we end up constructing a temporary variant, then memcpy-ing it over *this.