我正在构建一个动态动画和渲染系统,希望使用Boost.Units来表示物理量,以获得良好的维度安全性。然而,我将不得不向不知道Boost的函数传递数量数组,例如:
因此,假设对于
OpenGL缓冲区填充命令。它们只需要一个
const void *
,并期望在解引用时找到float
或double
值的数组。它们读取数据。来自BLAS和LAPACK不同实现的线性代数函数(如
gemm
或gesv
)。它们通常接受指向给定数组的float *
或double *
。它们同时读取和写入数据。
boost::units::quantity<U, T>
有一个const T& value()
成员,它可以直接引用包含的T
值。我还验证了boost::units::quantity<U, T>
是一个标准布局结构体,只有一个非静态数据成员,类型为T
。因此,假设对于
boost::units::quantity<U, T> q
,以下内容成立:
static_cast<const void*>(&q) == static_cast<const void*>(&q.value())
sizeof(q) == sizeof(T)
boost::units::quantity<U, T> a[100];
,是否可以安全地执行以下操作:
将
&a[0].value()
传递给一个期望在地址处读取100个类型为T
的对象数组的函数?将
reinterpret_cast<T*>(&a[0])
传递给一个将写入100个连续类型为T
的值到地址的函数?
我很清楚这可能是未定义行为,但现在我必须遵循“实用性胜过纯洁性”(1)原则。即使这是UB,它是否会按预期执行,或者会以不可预见的方式咬人?由于这可能是特定于编译器的:我需要现代MSVC(来自VS 2015)。
如果这不安全,是否有一种方法可以安全地实现此操作?其中“this”指的是“在OpenGL和仅具有C接口的数值计算机中使用Boost.Units”,而无需不必要地复制数据。
(1) 改编自Python之禅。