对std :: variant的访问没有访问

问题描述 投票:3回答:1

对于某些标准库类,访问其部分内容可能会合法地失败。通常你可以选择一种潜在的投掷方法,一种标记为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! (除了switching在variant::index()上的可怕的解决方法)

对我来说,这看起来像一个非常糟糕的设计疏忽...或者有这样的理由?如果我对监督是正确的,是否有一项计划在标准中解决这个问题?

c++ c++17 variant noexcept
1个回答
1
投票

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

你当然可以。只有在将值赋值给现有的variant时才会出现“无价值异常”状态。此外,根据定义,只有在这些过程中实际抛出异常时才会发生这种情况。这不是一个曾经发生在随机的variant的状态。

如果您承担责任确保您永远不会置换/分配给变体,或者您使用的类型从未在这些情况下抛出,或者您对这样做的任何异常做出响应,以致激发它的variant是没有被谈论(即:如果bad_alloc被抛出,你的应用程序没有抓住它;它只是关闭),那么你不必关心这种可能性。

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

© www.soinside.com 2019 - 2024. All rights reserved.