【问题标题】:noexcept visitation for std::variantstd::variant 的 noexcept 访问
【发布时间】:2019-05-25 13:54:05
【问题描述】:

对于某些标准库类,对其部分内容的访问可能会合法地失败。通常你可以在一些潜在的抛出方法和标记为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

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

但如果您查看std::visit(Visitor&amp;&amp; vis, Variants&amp;&amp;... vars),情况会变得更糟。没有 noexcept 替代它,虽然它只会抛出

如果 vars 中的任何变体是 valueless_by_exception

这意味着访问变体你不能选择自己承担责任,如果你别无选择,必须避免例外,你根本不能用标准工具访问std::variants! (除了switching 在variant::index() 上的可怕解决方法)

在我看来,这似乎是一个非常糟糕的设计疏忽……还是有原因?如果我对疏忽的看法是正确的,是否有计划在标准中解决这个问题?

【问题讨论】:

    标签: c++ c++17 variant noexcept


    【解决方案1】:

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

    当然可以。 “异常无价值”状态只有在您将值分配或置入现有variant 时才会发生。此外,根据定义,只有在这些过程中实际抛出异常时才会发生这种情况。这种状态绝不会发生在随机的variant 身上。

    如果您有责任确保您永远不会放置/分配给变体,或者您使用的类型永远不会在这些情况下抛出,或者您以@987654325引发它的 @ 没有被与之交谈(即:如果 bad_alloc 被抛出,您的应用程序不会捕获它;它只是关闭),那么您不必关心这种可能性。

    基本上,如果您已经编码以避免异常,visit 的非noexcept 状态是无关紧要的。除非抛出异常,否则variant 永远不会进入“异常无价值”。

    【讨论】:

    • 否:如果异常被禁用,std::visit 不存在于标准库中。
    • @Tobi:我不知道有任何编译器会在您禁用异常处理时主动删除noexcept 函数。我的一般理解是关闭异常处理要么删除throw 语句,要么导致它们终止应用程序。
    • 例如,如果你的目标是 macOS 10.13 和更早版本,Apple Clang 不允许你抛出 std::bad_variant_access(这是 C++ 运行时的问题,请参阅 here)。因此std::visit 在这种情况下不存在。
    • @Tobi:但这不是禁用异常的问题;这是一个不完整的 C++17 运行时问题。基本上,我的意思是 iOS/MacOS 处理其 C++ 运行时的方式的错,而不是标准的错。
    • 这不是真的,看看 libc++ implementation:它检查 valueless_by_exception() 然后传递给实际的实现,即 noexcept。
    猜你喜欢
    • 2017-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-07
    • 2019-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多