以 C++ 方式别名结构和数组 [英] Aliasing struct and array the C++ way

查看:35
本文介绍了以 C++ 方式别名结构和数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的另一个问题

在 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆