2015-09-25 66 views
5

我正在构建一个动态动画&渲染系统,我想用Boost.Units来表示物理量来获得很好的尺寸安全性。然而,我将不得不将数组的数量传递给对Boost一无所知的函数,例如:如何输入数字将数量数组加到底层类型?

  • OpenGL缓冲区填充命令。这些简单地取const void *,并期望在解引用它时找到一个floatdouble值的数组。他们读取数据。

  • 来自BLAS和LAPACK的不同实现的线性代数函数(例如gemmgesv)。这些通常将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];,是安全的:

  1. &a[0].value()传递给一个函数,该函数需要读取地址为?的地址为T的100个对象的数组。

  2. 通过reinterpret_cast<T*>(&a[0])函数将写入100个连续值类型T在地址?

我深知这可能是未定义行为,但现在我必须遵循“实用性节拍纯洁” (1)原则。即使这是UB,它会做预期的事,还是会以不可预知的方式咬人?由于这可能是编译器特定的:我需要这个用于现代MSVC(来自VS 2015)。

如果这不安全,是否有办法真正安全地做到这一点? “this”指的是“使用OpenGL和带有C接口的数字加法器使用Boost.Units”,没有不必要地复制数据。


(1)Zen of Python改编。

+0

我想,你说UB你的意思是IB?因为没有人应该摆脱UB。 – sehe

回答

2

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

有一件事你没有提到,应该添加到条件列表来检查,但是:包装数量类型的对齐应该与基础类型的对齐。 (见alignof)。

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

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

有了这些预先警告,不应该有UB,只是由于reinterpret_cast在特定平台上的语义导致的IB(实现定义的行为)。

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

+1

但违反严格的别名规则是UB,而不是IB。 (它违背了所谓的函数,就是BLAS/LAPACK/OpenGL C代码违反了它。) – dyp

+0

嗯。有这方面。我不知道这是否是一个问题,但它肯定是一个需要研究的领域。 – sehe

+0

@dyp严格的别名也是我的关注点。同时,在该地址处有*实际上是一个“float”类型的对象(作为'quantity'类型的完整对象的子对象)。所以也许严格的别名不会违反呢? – Angew

相关问题