如何访问存储在 std::variant 中的 class 的方法
How to access method of class stored in std::variant
我正在尝试访问 std::variant 中保存的 class 的方法。不幸的是它抛出以下错误:
class ’std::variant<A, int>’ has no member named ‘function’
代码:
class A {
private:
int number = 0;
public:
A() {};
void function(int i) {
number += i;
}
};
// ... main ...
std::variant<A,B> array[4][4];
array[0][0] = A(){};
array[0][0].function(3);
我试图阅读文档,但我仍然不明白我应该如何或是否应该使用 std::get() 和 std::variants.index() 来访问上述方法。
经过一些阅读,我尝试在循环中做这样的事情:
std::size_t t=array[i][j].index();
std::get<t>(array[i][j]).function();
不过还是不行。错误是:
note: candidate: template<class _Tp, class ... _Types> constexpr _Tp&& std::get(std::variant<_Types ...>&&)
constexpr inline _Tp&& get(variant<_Types...>&& __v)
template argument deduction/substitution failed:
std::get 是您正在寻找的解决方案。
std::get<A>(array[0][0]) = AA();
std::get<A>(array[0][0]).function(3);
或
std::get<int>(array[0][0]) = 56;
另外,您可以使用 std::array 代替此 C
数组,并获得更多标准库功能:
std::array<std::array<std::variant<A,int>, 4>, 4> array;
用法还是一样的,还是安全一点:
std::get<A>(std::get<0>(std::get<0>(array))) = A();
或:
std::get<A>(array.at(0).at(0)) = A();
在这种情况下,operator[]
数组的用法在索引错误的情况下可能不会引发错误。你最好使用 .at()
函数,它会在超出范围访问的情况下抛出异常:
try {
std::get<A>(array.at(0).at(0)) = A();
} catch (const std::out_of_range& e) {
std::cout << e.what() << std::endl;
}
编辑 - 模板参数 deduction/substitution 失败
std::size_t t = array[i][j].index();
std::get<t>(array[i][j]).function(); // Error!
您不能使用非常量值作为模板参数。模板参数在编译时进行分析,这里 t
仅在运行时才知道。请参考以下问题:
要在 std::variant
中初始化一个值,您可以使用 std::get
,或者从 C++17 开始,emplace()
:
array[0][0].emplace<A>();
要访问值,请使用 std::get
:
std::get<A>(array[0][0]).function(3);
此外,std::get
的模板参数必须在编译时已知,所以 std::get<t>
当 t
是一个变量时,将不起作用。你可以稍微不同地做,例如像这样:
std::size_t t = array[0][0].index();
switch (t) {
case 0:
std::get<0>(array[0][0]).function(3);
case 1:
// . . .
}
您调用 get 方法,将变体作为参数并为模板指定 class
ex: 假设你有一个点 class x,y 坐标
然后 std::get(v) 将允许您访问变量
中的点
std::variant<int, Point> v;
v = 177;
int i = std::get<int>(v);
v = Point(15,18);
try
{
Point s = std::get<Point>(v);
std::cout << s.getX();
}
catch (const std::bad_variant_access&) {}
我正在尝试访问 std::variant 中保存的 class 的方法。不幸的是它抛出以下错误:
class ’std::variant<A, int>’ has no member named ‘function’
代码:
class A {
private:
int number = 0;
public:
A() {};
void function(int i) {
number += i;
}
};
// ... main ...
std::variant<A,B> array[4][4];
array[0][0] = A(){};
array[0][0].function(3);
我试图阅读文档,但我仍然不明白我应该如何或是否应该使用 std::get() 和 std::variants.index() 来访问上述方法。
经过一些阅读,我尝试在循环中做这样的事情:
std::size_t t=array[i][j].index();
std::get<t>(array[i][j]).function();
不过还是不行。错误是:
note: candidate: template<class _Tp, class ... _Types> constexpr _Tp&& std::get(std::variant<_Types ...>&&)
constexpr inline _Tp&& get(variant<_Types...>&& __v)
template argument deduction/substitution failed:
std::get 是您正在寻找的解决方案。
std::get<A>(array[0][0]) = AA();
std::get<A>(array[0][0]).function(3);
或
std::get<int>(array[0][0]) = 56;
另外,您可以使用 std::array 代替此 C
数组,并获得更多标准库功能:
std::array<std::array<std::variant<A,int>, 4>, 4> array;
用法还是一样的,还是安全一点:
std::get<A>(std::get<0>(std::get<0>(array))) = A();
或:
std::get<A>(array.at(0).at(0)) = A();
在这种情况下,operator[]
数组的用法在索引错误的情况下可能不会引发错误。你最好使用 .at()
函数,它会在超出范围访问的情况下抛出异常:
try {
std::get<A>(array.at(0).at(0)) = A();
} catch (const std::out_of_range& e) {
std::cout << e.what() << std::endl;
}
编辑 - 模板参数 deduction/substitution 失败
std::size_t t = array[i][j].index();
std::get<t>(array[i][j]).function(); // Error!
您不能使用非常量值作为模板参数。模板参数在编译时进行分析,这里 t
仅在运行时才知道。请参考以下问题:
要在 std::variant
中初始化一个值,您可以使用 std::get
,或者从 C++17 开始,emplace()
:
array[0][0].emplace<A>();
要访问值,请使用 std::get
:
std::get<A>(array[0][0]).function(3);
此外,std::get
的模板参数必须在编译时已知,所以 std::get<t>
当 t
是一个变量时,将不起作用。你可以稍微不同地做,例如像这样:
std::size_t t = array[0][0].index();
switch (t) {
case 0:
std::get<0>(array[0][0]).function(3);
case 1:
// . . .
}
您调用 get 方法,将变体作为参数并为模板指定 class
ex: 假设你有一个点 class x,y 坐标 然后 std::get(v) 将允许您访问变量
中的点std::variant<int, Point> v;
v = 177;
int i = std::get<int>(v);
v = Point(15,18);
try
{
Point s = std::get<Point>(v);
std::cout << s.getX();
}
catch (const std::bad_variant_access&) {}