代码之家  ›  专栏  ›  技术社区  ›  Tobi

std::变体无异常访问

  •  3
  • Tobi  · 技术社区  · 7 年前

    对于一些标准的库类,对其部分内容的访问可能会合法地失败。通常,您可以在一些潜在的抛出方法和标记的方法之间进行选择 noexcept

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

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

    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) . 根本没有 它的替代品,尽管它只抛出

    如果vars中的任何变体 valueless_by_exception

    这意味着对于访问变体,您不能选择自己承担责任,如果您没有选择并且必须避免例外,则不能访问 std::variants 使用标准工具(除了可怕的解决方法 switch variant::index() )

    对我来说,这看起来是一个相当糟糕的设计疏忽。。。还是有原因?如果我对监督的看法是对的,那么在标准中有没有解决这个问题的方案?

    1 回复  |  直到 7 年前
        1
  •  2
  •   Nicol Bolas    7 年前

    这意味着你不能选择自己承担责任

    当然可以。“异常无价值”状态可以 如果将值赋给或放置到现有 variant . 此外,根据定义,只有在这些过程中实际抛出异常时,才会发生这种情况。这不是一个只发生在随机事件上的状态 变体

    如果您有责任确保您从未放置/分配变体,或者您使用的类型从未在这些情况下抛出,或者您以这样的方式响应任何异常,即 那激起了人们的不快 bad_alloc 被抛出时,应用程序无法捕获它;它只是关闭),然后你不必关心这种可能性。

    基本上,如果你 编码以避免异常,非- noexcept 的状态 visit 与此无关。不