以 C++ 方式别名结构和数组 [英] Aliasing struct and array the C++ way
问题描述
这是我的另一个问题
在 ISO C 之前的旧时代,以下代码不会让任何人感到惊讶:
In the old days of pre-ISO C, the following code would have surprised nobody:
struct Point {
double x;
double y;
double z;
};
double dist(struct Point *p1, struct Point *p2) {
double d2 = 0;
double *coord1 = &p1->x;
double *coord2 = &p2->x;
int i;
for (i=0; i<3; i++) {
double d = coord2[i] - coord1[i]; // THE problem
d2 += d * d;
}
return sqrt(d2);
}
不幸的是,这个有问题的行使用了指针算法(p[i]
根据定义 *(p + i))
在任何标准明确不允许的数组.C++17 草案 4659 在 8.7 [expr.add] 中说:
Unfortunately, this problematic line uses pointer arithmetic (p[i]
being by definition *(p + i))
outside of any array which is explicitely not allowed by the standard. Draft 4659 for C++17 says in 8.7 [expr.add]:
如果表达式 P 指向具有 n 个元素的数组对象 x 的元素 x[i],表达式 P + J 和 J + P(其中 J 的值为 j)指向(可能是假设的)元素x[i + j] 如果 0 <= i + j <= n;否则,行为未定义.
If the expression P points to element x[i] of an array object x with n elements, the expressions P + J and J + P (where J has the value j) point to the (possibly-hypothetical) element x[i + j] if 0 <= i + j <= n; otherwise, the behavior is undefined.
并且(非规范性)注释 86 使其更加明确:
And the (non-normative) note 86 makes it even more explicit:
出于此目的,不是数组元素的对象被视为属于单元素数组.一种超过 n 个元素的数组 x 的最后一个元素的指针被认为等价于指向假设元素的指针x[n] 用于此目的.
An object that is not an array element is considered to belong to a single-element array for this purpose. A pointer past the last element of an array x of n elements is considered to be equivalent to a pointer to a hypothetical element x[n] for this purpose.
引用问题的公认答案使用了这样一个事实,即 C 语言通过联合接受类型双关,但我在 C++ 标准中永远找不到等价物.所以我假设一个包含匿名结构成员和数组的联合会导致 C++ 中的 Undefined Behaviour
— 它们是不同的语言......
The accepted answer of the referenced question uses the fact that the C language accepts type punning through unions, but I could never find the equivalent in the C++ standard. So I assume that a union containing an anonymous struct member and an array would lead to Undefined Behaviour
in C++ — they are different languages...
在 C++ 中,像数组成员一样迭代结构体成员的合规方式是什么?我正在寻找当前 (C++17) 版本的方法,但也欢迎使用旧版本的解决方案.
What could be a conformant way to iterate through members of a struct as if they were members of an array in C++? I am searching for a way in current (C++17) versions, but solutions for older versions are also welcome.
它显然只适用于相同类型的元素,并且可以使用简单的assert
检测填充,如其他问题,所以填充、对齐和混合类型不是我的问题.
It obviously only applies to elements of same type, and padding can be detected with a simple assert
as shown in that other question, so padding, alignment, and mixed types are not my problem here.
推荐答案
使用成员指针的 constexpr 数组:
Use an constexpr array of pointer-to-member:
#include <math.h>
struct Point {
double x;
double y;
double z;
};
double dist(struct Point *p1, struct Point *p2) {
constexpr double Point::* coords[3] = {&Point::x, &Point::y, &Point::z};
double d2 = 0;
for (int i=0; i<3; i++) {
double d = p1->*coords[i] - p2->*coords[i];
d2 += d * d;
}
return sqrt(d2);
}
这篇关于以 C++ 方式别名结构和数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!