Motivation

Have direct access to common base class of std::variant .

struct Base { int pos ; }; struct A : Base { int a = 10 ; }; struct B : Base { int b = 20 ; }; std :: variant < A , B > var ; Base & base = std :: get < Base > ( var ); // can't do this // can do this, but this will cost you. Base & base = std :: visit ([]( Base & base ) -> Base & { return base ; }, var );

Final solution

variant_w_base < Base , std :: variant < A , B >> var ; Base & base = * var . base (); Base & base = var . get < Base > ();

source code

Step-by-step

To allow base class access, we store pointer to base.

template < class Base , class Variant > class variant_w_base { Base * m_base ; Variant m_variant ; void update_base (){ m_base = std :: visit ([]( auto && arg ) -> Base * { using Arg = std :: decay_t < decltype ( arg ) > ; if constexpr ( std :: is_same_v < Arg , std :: monostate > ){ return nullptr ; } else { return static_cast < Base *> ( & arg ); } }, m_variant ); } }

Each time value changed, copied, moved we update base class pointer.

Interface similar to std::variant , but all free functions are members.

Performance measurements

Accessing 100’000 element’s base class data. (aka dumb linear search). 100 repeats:

std::variant 21ms variant_w_base 2ms

Benchmark

P.S. It is also possible to use it as virtual class local storage, if you know all posible classes beforehand: