std::variant
提供以下访问功能:
std::get_if
:将指针带到variant
,将指针返回到替代。
template <std::size_t I, typename... Ts>
auto* std::get_if(std::variant<Ts...>* pv) noexcept;
如果
pv
不是空指针而是pv->index() == I
,则返回指向存储在pv
指向的变量中的值的指针。否则,返回空指针值。
这意味着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);
如果
v.index() == I
,则返回对v
中存储的值的引用。否则,抛出std::bad_variant_access
。
这意味着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
实施?
答案 0 :(得分:6)
正如@ T.C所指出的那样。在评论中,你的第一和第三个要求是互不相容的。这在N3279中有详细说明,标题为“保守地使用图书馆中的noexcept”。
基本上有两类合约:窄和宽。函数或操作的宽合约未指定任何未定义的行为。
这样的合同没有先决条件。只有具有广泛合同的函数在标准库中标记为noexcept
。
noexcept
。相反,你可以期待的最好的是它们被记录为“投掷:没什么。”
您似乎运气不好,并且std::variant
的当前提案中未提供此类未经检查的访问权限。
答案 1 :(得分:1)
我认为你必须自己实施整个变体。 虽然不受限制的工会可能会有所帮助 - 它们至少可以解决将多种类型放在同一位置并处理对齐问题。