在这个例子中,std::variant 是如何变成 valueless_by_exception 的?
How does std::variant becomes valueless_by_exception in this example?
这是受 cppreference
示例启发的示例
struct S {
operator int() { throw 42; }
};
int main(){
variant<float, int> v{12.f}; // OK
cout << std::boolalpha << v.valueless_by_exception() << "\n";
try{
v.emplace<1>(S()); // v may be valueless
}
catch(...){
}
cout << std::boolalpha << v.valueless_by_exception() << "\n";
}
对于一个编译器,我试过它输出
false, true
意味着 emplace
导致变体变得毫无价值
我不明白这是怎么发生的。
特别是我不明白为什么 emplace
被调用,我希望程序甚至不会调用它,因为从 S 到 int 参数的转换会抛出。
注意相关 std::variant::emplace
重载的签名:
template <size_t I, class... Args>
std::variant_alternative_t<I, variant>& emplace(Args&&... args);
它需要一组转发引用。这意味着在评估函数参数时不会调用从 S
到 int
的转换运算符;它在 emplace
的正文中被调用。由于尝试就地构建 int
会失败,因此变体因异常而变得毫无价值。
也许可以实现 variant
这样对于普通的可移动类型,在尝试就地构造之前保存旧值,然后在失败时恢复,但我不确定是否它符合标准对类型实现的各种限制。
这是受 cppreference
示例启发的示例struct S {
operator int() { throw 42; }
};
int main(){
variant<float, int> v{12.f}; // OK
cout << std::boolalpha << v.valueless_by_exception() << "\n";
try{
v.emplace<1>(S()); // v may be valueless
}
catch(...){
}
cout << std::boolalpha << v.valueless_by_exception() << "\n";
}
对于一个编译器,我试过它输出
false, true
意味着 emplace
导致变体变得毫无价值
我不明白这是怎么发生的。
特别是我不明白为什么 emplace
被调用,我希望程序甚至不会调用它,因为从 S 到 int 参数的转换会抛出。
注意相关 std::variant::emplace
重载的签名:
template <size_t I, class... Args>
std::variant_alternative_t<I, variant>& emplace(Args&&... args);
它需要一组转发引用。这意味着在评估函数参数时不会调用从 S
到 int
的转换运算符;它在 emplace
的正文中被调用。由于尝试就地构建 int
会失败,因此变体因异常而变得毫无价值。
也许可以实现 variant
这样对于普通的可移动类型,在尝试就地构造之前保存旧值,然后在失败时恢复,但我不确定是否它符合标准对类型实现的各种限制。