因为C++11 std::complex<T>[n]保证与T[n*2]相同,具有定义良好的值。这正是人们对任何主流建筑所期望的。对于我自己类型的标准C++,比如struct vec3 { float x, y, z; },这种保证是可以实现的,还是只有在编译器的特殊支持下才能实现?
发布于 2017-02-23 15:59:47
TL;DR:编译器必须检查reinterpret_cast,并确定std::complex的(标准库)专门化。我们不能一致地模仿语义。
我认为很明显,将三个不同的成员作为数组元素处理是行不通的,因为指向它们的指针的指针算法是非常有限的(例如,添加1会产生一个指针过去-结束)。
因此,让我们假设vec3包含一个由三个int组成的数组。即使这样,您隐式需要的底层reinterpret_cast<int*>(&v) (其中v是一个vec3)也不会给您留下指向第一个元素的指针。请参阅对指针-可转换性的详尽要求
两个对象
a和b是指针可互换的,如果:
c,使得a和c是指针可互转换的,而c和b是指针可互转换的.如果两个对象是可转换的指针,那么它们具有相同的地址,并且可以通过reinterpret_cast从指向另一个对象的指针中获得指向另一个对象的指针。数组对象及其第一个元素不是指针-可互转换的,尽管它们具有相同的地址。
这是非常明确的;虽然我们可以获得指向数组的指针(作为第一个成员),而指针间可转换性是传递的,但我们不能获得指向其第一个元素的指针。
最后,即使您设法获得指向成员数组的第一个元素的指针,如果您有一个vec3的数组,您也不能使用简单的指针增量遍历所有的成员数组,因为在这两者之间我们可以得到数组的指针。solve也不能解决这个问题,因为与指针相关联的对象不共享任何存储(具体而言,请参见[ptr.launder] )。
发布于 2017-02-23 15:44:17
它只有在编译器的特殊支持下才有可能,大多数情况下。
联合不能让您达到这个目的,因为通常的方法实际上有未定义的行为,尽管布局兼容的初始序列也有例外,而且您可以通过unsigned char*作为特例检查对象。不过仅此而已。
有趣的是,除非我们假定“以下”的含义广泛而无用,否则这一标准在技术上是自相矛盾的:
[C++14: 5.2.10/1]:..下面列出了可以使用reinterpret_cast显式执行的转换。不能使用reinterpret_cast显式执行其他转换。
然后没有提到complex<T>的情况。最后,您所指的规则是在[C++14: 26.4/4]中很久以后才引入的。
发布于 2017-02-23 15:47:20
我认为,如果您的类型包含float x[3],并且您确保了sizeof(vec3) == 3*sizeof(float) && is_standard_layout_v<vec3>,那么它将适用于单个float x[3]。在这些条件下,标准保证第一个成员的偏移量为零,因此第一个float的地址是对象的地址,您可以执行数组算法来获取数组中的其他元素:
struct vec3 { float x[3]; } v = { };
float* x = reinterpret_cast<float*>(&v); // points to first float
assert(x == v.x);
assert(&x[0] == &v.x[0]);
assert(&x[1] == &v.x[1]);
assert(&x[2] == &v.x[2]);您不能做的是将一个vec3数组看作一个浮动数组,它是长度的三倍。每个vec3中的数组上的数组算法不允许您访问下一个vec3中的数组。CWG 2182在这里是相关的。
https://stackoverflow.com/questions/42420116
复制相似问题