如果我有一个由3个double组成的类对象; x,y和z,是否可以在函数中循环遍历它们?
例如
for(i in (x,y,z))
do something;
我可以使用显式强制转换做类似的事情,但是我想知道是否有更优雅的解决方案。
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);
}
答案 0 :(得分:6)
从C ++ 20开始,我们可以将structured bindings与range-based for loop初始化语句(后者是C ++ 20的功能)结合在一起:
语法
for( init-statement(可选) 范围声明: range-expression )...
具体来说,在基于范围的for循环中将结构化绑定用作 init-statement :
#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;
}
但是,请注意,您只能使用结构化绑定来分解类的公共成员(在您的示例中,所有成员都是公共的)。此外,对于基于范围的for循环的 range-expression 中的初始化程序列表,您可能没有冲突的类型,这意味着此方法仅限于您的示例上下文:其中所有公共成员都属于相同的类型。
现在,如果您的类的(公共)成员及其实例都有非常简短的名称,我们可能需要考虑省略结构化绑定,而是直接对类成员进行列表初始化:
const Foo f(1., 2., 3.);
for (auto e : {f.x, f.y, f.z}) {
std::cout << e << " ";
} // 1 2 3
但是,尽管可以说是简短的,但缺点是我们不再从编译器获得任何帮助,无法确定我们是否实际上已完全分解了所有公共成员(不少于,不再更多),当存在时进行检查我们使用结构化绑定:
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
答案 1 :(得分:1)
for (auto&& i : std::vector<double>{x, y, z}){
// Do something, `i` is the double.
}
是一种方法,但以创建向量为代价。我不相信编译器会将此视作习惯用法并进行优化。
*(&x + 1)
这样的代码试图到达y
的行为是不确定的。 (指针算术仅在数组内有效。)
您不能为std::array
,std::vector
和x
使用y
或z
吗?