bad_variant_access不起作用

bad_variant_access not working

本文关键字:不起作用 access variant bad      更新时间:2023-10-16

当变体不在列表中时,我正在尝试获得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例外

法典

std::visit只有在变体valueless_by_exception时才会触发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 已经回答了为什么你可以首先使用char(通过重载选择构造(来构造你的变体。

您不能通过尝试首先以抛出的方式构造变体来触发bad_variant_access,因为 [variant.ctor] 指示构造函数将重新引发该异常(在本例中为int(。

根据std::variant的文档:

变量的构造函数执行以下操作:

构造一个包含替代类型的变体T_j,如果同时在范围内对 Types... 的每个T_i都有虚函数 F(T_i( 的重载,则表达式 F(std::forward(t((

将通过重载分辨率选择表达式 F(std::forward(t((。[...]

即 std::variant 将获得第一个可从传递的参数构造的类型。在这种情况下,int可以从char构造,因此变体被赋值为这样。