bad_variant_access无效

时间:2017-08-18 16:06:18

标签: c++ stl c++17

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

Code

2 个答案:

答案 0 :(得分:2)

根据std::variant的文档:

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

  

如果每个T_i都存在虚函数F(T_i)的重载,则构造一个包含替代类型T_j 的变量,该变量将由表达式F(std :: forward(t))的重载决策选择。类型...... 同时在范围内。 [...]

即。 std :: variant将从传递的参数中获取可构造的第一个类型。在这种情况下,int可以从char构建,因此变体会被指定为此类。

答案 1 :(得分:2)

如果变体为valueless_by_exception,则

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';
    }
}

Demo

Frank already answered为什么你可以使用char(通过重载选择的结构)来构建你的变体。

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