有没有办法在 C++ 中循环对象的不同数据成员

Skc*_*ica 7 c++

如果我有一个由 3 个双打组成的类对象;x、y 和 z,有没有办法在函数中循环它们?

例如

for(i in (x,y,z))
    do something;
Run Code Online (Sandbox Code Playgroud)

我可以用显式转换做类似的事情,但我想知道是否有更优雅的解决方案。

class testc {
public:
    double x, y, z;

    testc(double x, double y, double z)
        :x(x), y(y), z(z)
    {}
};

int main()
{
    testc omega(1, 2, 3);
    cout << *(double*)&omega << " " << *((double*)&omega +1) << " " << *((double*)&omega +2);
}
Run Code Online (Sandbox Code Playgroud)

dfr*_*fri 6

(C++20) 循环已知数量的公共成员:基于范围的 for 循环初始化语句中的结构化绑定

从 C++20 开始,我们可以将结构化绑定基于范围的 for 循环初始化语句结合起来(后者是 C++20 的特性):

语法

for ( init-statement(optional) range-declaration : range-expression ) ...

具体来说,在基于范围的 for 循环中使用结构化绑定作为init 语句

#include <iostream>

class Foo {
public:
    double x, y, z;

    Foo(double x, double y, double z) : x(x), y(y), z(z) {}
};

int main() {
    const Foo foo(1., 2., 3.);

    for (auto [x, y, z] = foo; auto e : {x, y, z}) {
        std::cout << e << " ";
    } // 1 2 3

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是请注意,您只能使用结构化绑定来分解类的公共成员(在您的示例中,所有成员都是公共的)。此外,对于基于范围的 for 循环的范围表达式中的初始值设定项列表,您可能没有冲突的类型,这意味着这种方法仅限于您的示例的上下文:所有公共成员都属于同一类型。

为什么要使用结构化绑定而不是直接对类成员进行列表初始化?

现在,如果您的类的(公共)成员以及它的实例都有非常简短的名称,我们可能要考虑省略结构化绑定,而是直接对类成员进行列表初始化:

const Foo f(1., 2., 3.);
for (auto e : {f.x, f.y, f.z}) {
    std::cout << e << " ";
} // 1 2 3
Run Code Online (Sandbox Code Playgroud)

然而,尽管可以说更简洁,但缺点是我们不再从编译器那里得到任何帮助来发现我们是否实际上已经完全分解了所有公共成员(不少于,不多于),当我们使用结构化绑定:

for (auto [x, y] = foo; auto e : {x, y}) { /* ... */ }
// error: type 'Foo' decomposes into 3 elements, 
//        but only 2 names were provided

for (auto [x, y, z, xx] = foo; auto e : {x, y, z, xx}) { /* ... */ }
// error: type 'Foo' decomposes into 3 elements, 
//        but 4 names were provided
Run Code Online (Sandbox Code Playgroud)