What are the downsides to make a part of std::variant class an explicit conversion (to alternative) operator overloadings set in addition to (or even instead of) get< T >() free functions (p.568 of the draft)?
template<class... Types>
class variant
{
template<class T>
explicit operator const T& () const&;
template<class T>
explicit operator T& () &;
template<class T>
explicit operator const T&& () const &&;
template<class T>
explicit operator T&& () &&;
};
Is it unsafe in some contexts? Why do we need free get() function (namely, "type" version, not "index" one), when variant exposes a value semantic (cite from the draft):
A variant object holds and manages the lifetime of a value.
Isn't it enough to make a variant explicitly convertible to alternative, but still implicitly constructible from an alternative?
I know, the uniformity of the interface is good thing (I remember we need get< I >() along with get< T >()), but I think it is more natural way to get containing alternative value simply by converting to it, rather then applying some function specialization to variant instance.
I can think of a few downsides:
std::variant can hold cv void, but conversion functions returning cv void& and cv void&& would be illegal, and conversion functions to cv void are never called ([class.conv.fct]/1);std::variant to hold a type that can also be constructed from it, e.g.: std::variant<std::monostate, std::any> v; std::any a{v}; - what should happen in this case?In addition, currently it is possible to take a function returning T, convert it to a function returning std::variant<T, U> and expect the compiler to detect all cases where code needs to be changed; with a conversion function to T any cases where code was copying or binding a reference to T would result in a bug:
int f();
int i{f()}; // OK
// f() changes to:
std::variant<int, std::string> f();
int i{f()}; // can now throw std::bad_variant_access
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With