C++ Logo

std-discussion

Advanced search

Re: std::variant - going from Alternative& to the enclosing variant&

From: Ville Voutilainen <ville.voutilainen_at_[hidden]>
Date: Fri, 21 Aug 2020 18:40:48 +0300
On Fri, 21 Aug 2020 at 18:13, Victor Khomenko
<victor.khomenko_at_[hidden]> wrote:
>
> > I don't think so. The magic-function you suggest would seemingly need to be
> > told what kind of a variant to convert to.
>
> True. One can do static sanity checks, that the type is indeed a variant and that it has the type of the function's argument as an alternative. Moreover, you'll have to do something with the object returned by the function - e.g. assign it to some variable, and if the type is wrong, you'll get a type mismatch error. So even though one can theoretically make this mistake and still get the code compiled, I think the danger is minimal in practice - I'd compare this to calling a wrong function by accident.

I'm afraid it's worse than that:

template <class... VariantTypes, class ElementType>
variant<VariantTypes> variant_from_element(ElementType&& element);

In your visitor's call operator, you do

auto& var = variant_from_element<int, string>(my_arg);

That always compiles (at least if the type of my_arg is one of the
element types of the variant).
If called with a variant that has different elements (such as
variant<string, int>),
you get an invalid reference, as you said. Fiddling with it is UB.
Furthermore, if you have
variant<int, string, string>, you wouldn't know which string element
it is. Passing the variant into the visitor
allows your visitor to query from the variant which index is active,
and thus that approach can cope
with variants that have multiple elements of the same type. It's
certainly possible in variant_from_element
to check that the ElementType is one of VariantTypes, and reject calls
for variants that have multiple
elements of the argument type, but neither of those problems even
arises with the pass-the-variant-in approach.

Received on 2020-08-21 10:44:26