Вариант: нет подходящей функции для вызова get

Вот мой код:

#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();
}

(см. wandbox.org)

Я получаю ошибку no matching function for call to 'get' но я не понимаю, почему. std::variant::index() является constexpr, так что это не проблема (я проверил, поставив непосредственно значение 1, но все та же ошибка).
у меня есть std::monostate для предотвращения пустого варианта (когда нет аргументов в typename... Args)

2 ответа

Решение

m_variant.index() это значение времени выполнения (как m_variant не является постоянным выражением).

Способ отправки - использовать посетителя, так как:

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

демонстрация

Что-то помечено constexpr говорит вам, что в определенных ситуациях он может быть вызван во время компиляции. Это не гарантирует, что его всегда можно вызвать во время компиляции.

Я в случае variant, index может вызываться во время компиляции, если сам вариант является значением constexpr. В противном случае это метод времени выполнения.

Вы можете либо прочитать документацию о том, когда что-то может быть вызвано во время компиляции, либо рассуждать об этом; в этом случае, если тип варианта может изменяться во время выполнения, как можно index быть постоянной времени компиляции? Помните, что только ttpe и constexprness значений, плюс, если они сами находятся в контексте времени компиляции, могут быть использованы для рассуждения о том, "может ли это быть вызвано во время компиляции".

Другие вопросы по тегам