std::variant 提供以下访问功能:

  • std::get_if :获取指向 variant 的指针,返回指向替代的指针。
    template <std::size_t I, typename... Ts>
    auto* std::get_if(std::variant<Ts...>* pv) noexcept;
    


  • 这意味着 get_if 的实现大致如下所示:
    template <std::size_t I, typename... Ts>
    auto* std::get_if(std::variant<Ts...>* pv) noexcept
    {
        if(pv == nullptr) return nullptr;
        if(pv->index() != I) return nullptr;
        return &(pv->real_get<I>());
    }
    
  • std::get :引用 variant ,返回对替代的引用,throw 无效访问。
    template <std::size_t I, typename... Ts>
    auto& std::get(std::variant<Ts...>& v);
    


  • 这意味着 get 的实现大致如下所示:
    template <std::size_t I, typename... Ts>
    auto& std::get(std::variant<Ts...>& v)
    {
        if(v.index() != I) throw std::bad_variant_access{};
        return v.real_get<I>();
    }
    


  • 我想要一个不安全的访问函数:
  • noexcept
  • 引用 variant ,避免任何 pv == nullptr 检查。
  • 如果 v.index() != I 有未定义的行为。

  • 为什么?因为在某些情况下,我 100% 确定特定 variant 实例在代码路径中包含特定类型。此外,在编写已经单独检查 v.index() != I (例如编写我自己的 visit )的通用代码时,这将很有用。

    示例实现:
    template <std::size_t I, typename... Ts>
    auto& unsafe_get(std::variant<Ts...>& v)
    {
        return v.real_get<I>();
    }
    

    标准中有这样的吗? 我找不到。如果没有, 是否可以为 std::variant 实现,或者我是否需要推出自己的 variant 实现?

    最佳答案

    正如@T.C. 指出的那样在评论中,您的第一个和第三个愿望是相互不兼容的。这在 N3279 中有详细说明,标题为“图书馆中 noexcept 的保守使用”。

    基本上有两类契约(Contract):窄契约(Contract)和宽契约(Contract)。一个函数或操作的 契约没有指定任何未定义的行为。
    这样的契约(Contract)没有先决条件。在标准库中,只有具有宽契约(Contract)的函数才被标记为 noexcept

    OTOH,一个 窄的 合约是一个不宽的合约。当以违反文档约定的方式调用时,函数或操作的窄契约会导致 未定义行为 。它们不能被标记为 noexcept 。相反,您可以期待的最好结果是它们被记录为“抛出:没有”。

    看来你运气不好,当前的提案中没有提供这种未经检查的访问 std::variant

    关于c++ - 不安全, `noexcept` 和访问 `std::variant` 的无开销方式,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42052122/

    10-12 23:56