当变量不在列表中时,我试图获得std::bad_variant_access
异常。但是下面的代码不起作用,它返回一个隐式转换的ASCII int值
我应该做哪些更改,这种变体对类型选择是严格的
#include <iostream>
#include <variant>
using namespace std;
struct printer
{
void operator()(int x) {
cout << x << "i"<<endl;
}
void operator()(float x) {
cout << x << "f"<<endl;
}
void operator()(double x)
{
cout << x << "d" << endl;;
}
};
int main() {
using my_variant = std::variant<int, float, double>;
my_variant v0('c');
try {
std::visit(printer{}, v0);
}
catch(const std::bad_variant_access& e) {
std::cout << e.what() << '\n';
}
return 0;
}
输出:
部99i
我希望得到std::bad_variant_access
例外
答案 0 :(得分:2)
根据std::variant
的文档:
变体的构造函数执行以下操作:
如果每个T_i都存在虚函数F(T_i)的重载,则构造一个包含替代类型T_j 的变量,该变量将由表达式F(std :: forward(t))的重载决策选择。类型...... 同时在范围内。 [...]
即。 std :: variant将从传递的参数中获取可构造的第一个类型。在这种情况下,int
可以从char
构建,因此变体会被指定为此类。
答案 1 :(得分:2)
std::visit
只会触发bad_variant_access
异常(C ++ 17,请参阅N4659 23.7.3.5 [variant.status])
这意味着如果您尝试以引发异常的方式设置变体值,则该变体将保持“无值”状态,因此不允许访问。
要触发它,我们可以像这样更改代码:
struct S{
operator int() const{throw 42;}
};
struct printer{//as before};
int main() {
using my_variant = std::variant<int, float, double>;
my_variant v0{'c'};
try{
v0.emplace<0>(S());
}catch(...){}
try {
std::visit(printer{}, v0);
}
catch(const std::bad_variant_access& e) {
std::cout << e.what() << '\n';
}
}
Frank already answered为什么你可以使用char
(通过重载选择的结构)来构建你的变体。
你不能通过尝试首先以一种方式构造变量来触发bad_variant_access
,因为[variant.ctor]指示构造函数将重新抛出该异常(在本例中为int
)