C++ Logo


Advanced search

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

From: Victor Khomenko <victor.khomenko_at_[hidden]>
Date: Fri, 21 Aug 2020 14:06:47 +0000
Dear all,

[I searched the list's archive but didn't find anything relevant.]

Problem: How to change the value of a variant from within a visitor? Unfortunately, there is no straightforward way to do that, as the relevant operator()(Alternative&) of the visitor has no access to the enclosing std::variant.

Motivating Example 1: Suppose a visitor is called on an instance of std::variant<Caterpillar,Butterfly> that holds a Caterpillar object, and the visitor wants to turn this Caterpillar into a Butterfly.

Motivating Example 2: A practical scenario would be processing of tree-like structures e.g. terms or parse trees/ASTs; e.g. a visitor for simplifying algebraic expressions may want to replace a subtree of the form 0*ANY by 0, which modifies the type of the node from Multiply to Number.

Not only this problem is annoying, but it's also messy to work around - the easiest workaround I could think of is to store a pointer to std::variant inside a visitor - which entails defining a constructor and some mechanism for updating this pointer if the visitor object is to be re-used (re-using the visitor is common for recursive processing of tree-like structures).

Proposed solution: It would be nice to have a standard function that would turn Caterpillar& to variant<Caterpillar,Butterfly>& (with overloads for const& and &&). I (perhaps, naively) believe it can be implemented via a type cast (subtracting the offset of the storage within the invariant type, if it's not 0).

The disadvantages I can see are:
  (1) this function would be more difficult, and would require overheads like back-pointers, if an analogue of boost::reference_wrapper is to be supported in future;
  (2) if a Caterpillar object is stand-alone and not within a variant, the function will return an invalid reference (i.e. we will have undefined behaviour) and so it's the responsibility of the programmer to use this function only for objects inside variants, e.g. from within visitors.

However, (1) seems unlikely, and I think the advantages of having this function far outweigh (2) - the described workaround that maintains a pointer in a visitor is much more verbose and error-prone.

What do you think? Can you kill the idea or it's worth submitting a proposal?


Received on 2020-08-21 09:10:16