Ardakaniz
Ardakaniz

Reputation: 165

Variant: no matching function for call to 'get'

Here's my code:

#include <iostream>
#include <variant>
#include <vector>

class A {
public:
    virtual void Foo() = 0;    
};

class B : public A {
public:
    void Foo() override {
        std::cout << "B::Foo()" << std::endl;   
    }
};

class C :public A {
public:
    void Foo() override {
        std::cout << "C::Foo()" << std::endl;   
    }
};

template<typename... Args>
class D {
public:
    template<typename T>
    void Foo() {
        m_variant = T{};
    }

    void Bar() {
      std::get<m_variant.index()>(m_variant).Foo();
    }

private:
    std::variant<std::monostate, Args...> m_variant;
};

int main() {
    D<B, C> d;
    d.Foo<B>();
    d.Bar();

    d.Foo<C>();
    d.Bar();
}

(c.f wandbox.org)

I'm getting the error no matching function for call to 'get' but I don't figure out why. std::variant::index() is constexpr, so it isn't the problem (I tested by putting directly the value 1, but still the same error).
I have a std::monostate to prevent an empty variant (when no args are in typename... Args)

Upvotes: 3

Views: 3442

Answers (2)

Jarod42
Jarod42

Reputation: 217085

m_variant.index() is a runtime value (as m_variant is not a constant expression).

The way to dispatch is to use visitor, as:

std::visit([](auto& v) { v.Foo(); }, m_variant);

Demo

Upvotes: 6

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275230

Something marked constexpr tells you that in certain situations it can be called at compile time. It does not guarantee it can always be called at compile time.

I the case of variant, index can be called at compile time if the variant itself is a constexpr value. Otherwise it is a runtime method.

You can either read documentation about when something can be called at compile time, or reason about it; in this case, if the type of variant could vary at runtime, how can index be a compile time constant? Remember that only the ttpe and constexpr ness of values, plus if itself is in a compile time context, can be used to reason about "can this be called at compile time".

Upvotes: 1

Related Questions