访问"std::variant"的不安全、"noexcept"和无开销方式
Unsafe, `noexcept` and no-overhead way of accessing `std::variant`
std::variant
提供以下访问功能:
-
std::get_if
:将指针带到variant
,将pointer返回到备选方案。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
实现
正如@T.C.在评论中指出的,您的第一个和第三个需求是相互不兼容的。这在N3279中有详细说明,标题为"图书馆中保守使用noexcept"。
基本上有两类合同:狭义合同和广义合同。函数或操作的宽约定不指定任何未定义的行为。这样的合同没有任何先决条件。在标准库中,只有具有宽协定的函数才会标记为noexcept
。
OTOH,窄合同是不宽的合同。当以违反文档约定的方式调用时,函数或操作的狭义约定会导致未定义的行为。它们不能标记为noexcept
。相反,你能期待的最好的结果是,它们被记录为"投掷:什么都没有">
看来您运气不好,std::variant
的当前提案中没有提供这种未经检查的访问。
我认为您必须自己实现整个变体。尽管不受限制的联合可能会有所帮助,但它们至少可以解决将多个类型放在同一位置并处理对齐问题的问题。
- 如何在c++中为模板函数实例创建快捷方式
- 在c代码之间共享数据的最佳方式
- 在C++中将函数压缩为两种方式
- 以螺旋方式打印矩阵的程序.(工作不好)
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- 创建引用向量的优雅方式
- Constexpr替代了新的放置方式,可以让内存中的对象保持未初始化状态
- 使用QQuickFramebufferObject时同步数据的最佳方式是什么
- 不同/较旧的处理器运行c++代码的方式是否不同
- 从嵌套在std::映射中的std::列表中删除元素的最佳方式
- 如果条件为TRUE(最佳方式?),则在do while循环中后置增量
- 重载方法的方式会在使用临时调用时生成编译器错误
- 在reactor中存储eventHandlers的最佳方式是什么
- 如何以优化的方式同时迭代两个间距不相等的数组
- 以线程安全的方式调用"QQuickPaintedItem::updateImage(const QImage&image)"(no QThread)
- 为什么C++有不同的变量初始化方式?
- 在AVX通道中混洗的最佳方式
- 如何重新定义MPI_FLOAT,MPI_DOUBLE以 typedef 的方式
- 如何以静态代码分析友好的方式使用 #define 防护?
- 以迭代方式合并标准::unordered_map