Вариант: нет подходящей функции для вызова 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 значений, плюс, если они сами находятся в контексте времени компиляции, могут быть использованы для рассуждения о том, "может ли это быть вызвано во время компиляции".