没有std::变体的例外访问



对于某些标准库类,访问其部分内容可能会失败。通常,您可以在一些潜在的抛出方法和标记为noexcept的方法之间进行选择。后者在前提条件下省去了检查,所以如果你想自己承担责任,你可以。这可以在不允许使用异常的情况下使用,或者在修复性能瓶颈时使用。

示例1:std::vector元素访问:

std::vector<int> vec;
vec.at(n) // throws std::out_of_range
vec[n] // potentially UB, thus your own responsibility

示例2:std::optional访问:

std::optional<int> optn;
optn.value() // throws std::bad_optional_access
*optn // potentially UB, thus your own responsibility

现在转到std::variant。直接访问替代方案在某种程度上遵循以下模式:

std::variant<std::string, int> var;
std::get<int>(var) // potentially throwing std::bad_variant_access
*std::get_if<int>(&var) // potentially UB, thus your own responsibility

但这一次签名更改,我们必须注入*&。这样做的缺点是我们无法获得自动移动语义。还有一件事要记住。。。

但如果你看一下std::visit(Visitor&& vis, Variants&&... vars),情况会变得更糟。虽然它只抛出,但没有noexcept可供选择

如果vars中的任何变量是valueless_by_exception。

这意味着对于访问变体,您不能选择自己承担责任,如果您别无选择,必须避免出现异常,则根本无法使用标准工具访问std::variants!(除了switchvariant::index()上的糟糕变通方法之外)

对我来说,这看起来是一个相当糟糕的设计疏忽。。。或者这是有原因的?如果我对监督的看法是正确的,有没有在标准中解决这个问题的举措?

这意味着对于访问变体,您不能选择自己承担责任

当然可以。只有在现有variant中分配或设置值时,才会出现"异常无值"状态。此外,根据定义,只有在这些过程中实际抛出异常时,才会发生这种情况。这不是一种只发生在随机CCD_ 13上的状态。

如果你有责任确保你永远不会对变体进行模板/赋值,或者你使用的类型在这种情况下永远不会抛出,或者你对任何异常的响应方式是不会与引发它的variant对话(即:如果抛出bad_alloc,你的应用程序就不会捕获它;它只是关闭),那么你就不必在意这种可能性了。

基本上,如果已经编码以避免异常,那么visit的非noexcept状态是不相关的。除非抛出异常,否则任何variant都不会进入"异常无值"。

相关内容

  • 没有找到相关文章

最新更新