Search code examples
c++c++17variant

std::variant of classes with same base class


I'm not fully comprehending variants' usage, maybe someone can clear up what I'm doing wrong (possibly my approach).

Let the variant object be _Types of two classes, both inheriting the same class.

class base
{
public:
    int foo;
};
class a: public base
{
    int bar;
};
class b: public base
{
    float bar;
};

byte variant_id = 0; // 0 for class A, 1 for class B
std::variant< base, a, b > variant;

Here's how I use the variant:

void func( )
{
    auto& _variant = std::get< base >( variant ); // ideally would be = variant_id ? std::get< b >( variant ) : std::get< a >( variant )
    _variant.foo = 20;

    if ( variant_id == 1 )
    {
        auto& variant_ = std::get< b >( variant );
        variant_.bar = 20.f;
    }
    else
    {
        auto& variant_ = std::get< a >( variant );
        variant_.bar = 20;
    }

Maybe a union is more effective?

union
{
    a _a;
    b _b;
} variant;
byte variant_id = 0;

Solution

  • Try not to query the variant for what type it holds. If you do, your code is essentially equivalent to a bunch of dynamic casts in an if chain, a code smell.

    Instead, let the variant dispatch for you. And if you want to access the common base of a and b, you do not need a base member in that variant.

    Use a visitor

    std::variant< a, b > var;
    void func( )
    {
       std::visit([](auto&& v) {
         v.foo = 20; // Both `a` and `b` have a foo, this is well formed.
         v.bar = 20; // Both have a `bar` that can be assigned a 20. This is well formed too
       }, var);
    }