如何将 Boost 数量数组类型化为基础类型?

How to type-pun Boost quantity arrays to the underlying type?

我正在构建一个动态动画和渲染系统,我想使用 Boost.Units 来表示物理量以获得良好的尺寸安全性。但是,我将不得不将数量数组传递给对 Boost 一无所知的函数,例如:

我知道 boost::units::quantity<U, T> 有一个 const T& value() 成员,它提供对包含的 T 值的直接引用访问。我还验证了 boost::units::quantity<U, T> 是一个标准布局结构,只有一个非静态数据成员,类型为 T.

因此,我们假设对于 boost::units::quantity<U, T> q,以下成立:

我的问题是:给定一个数组boost::units::quantity<U, T> a[100];,是否安全:

  1. &a[0].value() 传递给一个函数,该函数期望在地址处读取 100 个类型为 T 的对象的数组?

  2. reinterpret_cast<T*>(&a[0]) 传递给函数,该函数将在地址处写入 100 个 T 类型的连续值?

我很清楚这可能是未定义的行为,但现在我必须遵循 "Practicality beats purity"(1) 原则。即使这是 UB,它会做预期的事情,还是会以无法预料的方式咬人?因为这可能是特定于编译器的:我需要这个用于现代 MSVC(来自 VS 2015)。

如果这不安全,有没有办法真正安全地做到这一点?使用 "this" 引用 "using Boost.Units with OpenGL and with number crunchers which only have a C interface," 而不会 不必要地复制数据。


(1) 改编自 Zen of Python.

是的,这看起来像你可以做的事情。

有一件事你没有提到,但是应该添加到要检查的条件列表中:包装金额类型的对齐方式应该与基础类型的对齐方式相匹配。 (参见 alignof)。

因此,在实践中,我只会使用一些 static_asserts¹ 来编写这样的代码,以保护使重新解释有效的假设。

如果加上 T 与 remove_cv_t<decltype(q.value())> 相同的断言,这应该是可靠的。

有了这些预防措施,由于您特定平台上 reinterpret_cast 的语义,不应该有 UB,只有 IB(实现定义的行为)。

¹ 并且也许调试断言 &q.value() == &q