不安全,使用noexcept和访问std :: variant的开销方法 [英] Unsafe, `noexcept` and no-overhead way of accessing `std::variant`

查看:107
本文介绍了不安全,使用noexcept和访问std :: variant的开销方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

std::variant provides the following access functions:

  • std::get_if :以指针variant,将 pointer 返回给替代项.

  • std::get_if: take pointer to variant, return pointer to alternative.

template <std::size_t I, typename... Ts> 
auto* std::get_if(std::variant<Ts...>* pv) noexcept;

    • 如果pv不是空指针,并且pv->index() == I,则返回指向存储在pv指向的变量中的值的指针.否则,返回空指针值.

      If pv is not a null pointer and pv->index() == I, returns a pointer to the value stored in the variant pointed to by pv. Otherwise, returns a null pointer value.

      这意味着get_if的实现大致如下:

      This means that get_if's implementation roughly looks like this:

      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,将 reference 返回替代项, throw 用于无效访问.

      std::get: take reference to variant, return reference to alternative, throw on invalid access.

      template <std::size_t I, typename... Ts>
      auto& std::get(std::variant<Ts...>& v);
      

        • 如果为v.index() == I,则返回对存储在v中的值的引用.否则,抛出std::bad_variant_access.

          If v.index() == I, returns a reference to the value stored in v. Otherwise, throws std::bad_variant_access.

          这意味着get的实现大致如下:

          This means that get's implementation roughly looks like this:

          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检查.

          Takes a reference to a variant, avoiding any pv == nullptr check.

          具有未定义的行为.

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

          Why? Because there may be some situations where I am 100% sure that a particular variant instance contains a specific type in a code path. Also, it would be useful when writing generic code that already separately checked v.index() != I (e.g. writing my own visit).

          示例实现:

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

          标准中是否存在类似的内容??如果不是,是否可以为std::variant实施,还是我需要推出自己的variant实施?

          Is there something like this in the standard? I couldn't find it. If not, is this possible to implement for std::variant, or do I need to roll out my own variant implementation?

          推荐答案

          @ T.C.指出.在注释中,您的第一个和第三个需求者是彼此不兼容的. N3279 ,标题为在图书馆中保守使用noexcept".

          As pointed out by @T.C. in the comments, your first and third desiderata are mutually incompatible. This was spelled out in N3279, titled "Conservative use of noexcept in the Library".

          本质上有两类合同:窄合同和宽合同.功能或操作的范围合同未指定任何未定义的行为. 这样的合同没有任何先决条件.标准库中仅将具有广泛合同的功能标记为noexcept.

          There are essentially two classes of contracts: narrow and wide. A wide contract for a function or operation does not specify any undefined behavior. Such a contract has no preconditions. Only functions with wide contracts are marked noexcept in the Standard Library.

          OTOH,合约是不广泛的合约.以违反书面合同的方式调用功能或操作的狭窄合同会导致不确定的行为.它们不能标记为noexcept.取而代之的是,您可以期望的最好是将它们记录为"Throws:Nothing".

          OTOH, a narrow contract is a contract which is not wide. Narrow contracts for a functions or operations result in undefined behavior when called in a manner that violates the documented contract. They cannot be marked noexcept. Instead, the best you can expect is that they are documented as "Throws: Nothing."

          您似乎很不走运,并且在std::variant的当前建议中没有提供这种未经检查的访问权限.

          It appears that you are out of luck and no such unchecked access is provided in the current proposals for std::variant.

          这篇关于不安全,使用noexcept和访问std :: variant的开销方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆