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/