不安全,使用noexcept和访问std :: variant的开销方法 [英] Unsafe, `noexcept` and no-overhead way of accessing `std::variant`
问题描述
std::variant
提供以下访问功能:
std::variant
provides the following access functions:
-
std::get_if
:以指针到variant
,将 pointer 返回给替代项.
std::get_if
: take pointer tovariant
, 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 andpv->index() == I
, returns a pointer to the value stored in the variant pointed to bypv
. 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 tovariant
, 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 inv
. Otherwise, throwsstd::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 anypv == 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 checkedv.index() != I
(e.g. writing my ownvisit
).示例实现:
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 ownvariant
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屋!
-
-