问题描述
我在 struct Flags
中有很多 bool 变量:
struct Flags
{
bool isATrue;
bool isBTrue;
bool isCTrue;
...
}
然后在另一个函数中我计算了这些变量的布尔结果值,
现在我必须把在新的 Vector.e.g. 中为真的变量如果isBtrue == true
。我必须将 isBtrue
放入向量 TrueFlags
。
但是 C++ 不支持 for() 循环来迭代结构。有人有什么好主意吗?如何在 C++ 中迭代结构?
解决方法
您可以使用 std::bitset
并拥有:
// 3 stands for 3 flags you have in your struct
std::bitset<3> flags;
flags.set(0); // set bit at position 0 to true
flags.set(2); // set bit at position 2 to true
然后你可以循环遍历它:
for (std::size_t i{ 0 }; i < flags.size(); ++i) {
// access with flags[i]
}
您还可以为直接标志访问创建一个枚举,例如:
enum Flags {
IsATrue = 0,IsBTrue,IsCTrue
};
然后像这样使用它:flags[IsATrue]
。
如果值的数量是固定的并且事先知道,可以使用array<bool>
,否则使用vector<bool>
。同样对于 is_true 变量。然后你可以轻松地循环它。
一种方法是使用其他答案中所述的位集。
但是,如果结构 Flags
是您必须使用的东西(出于任何原因,例如可能存在的 API 等),您可以使用操作包装器和指向成员的指针来实现“循环能力”。类似(见Live):
struct Flags
{
bool isATrue;
bool isBTrue;
bool isCTrue;
};
struct FlagsOp
{
FlagsOp(Flags& f)
: f{ f },v({ &Flags::isATrue,&Flags::isBTrue,&Flags::isCTrue })
{}
size_t size() const { return v.size();}
bool& operator[](size_t n) { return f.*(v[n]); }
private:
Flags& f;
vector<bool Flags::*> v;
};
int main()
{
Flags f{};
FlagsOp fop(f);
fop[0] = true; // isATrue
fop[1] = true; // isBTrue
fop[2] = true; // isCTrue
for (size_t i = 0; i < fop.size(); ++i)
cout << fop[i] << '\n';
}
,
如果您不想更改您的 struct Flags
,还有另一种方法。但首先请阅读 this 并注意这不是一个可移植的解决方案。
您可以通过定义这样的联合来利用联合:
union Flagsunion{
bool flag[sizeof(Flags)/ sizeof(bool)];
Flags flags;
};
假设您的 std::vector<bool>
的名称是 myvector
而您的 Flags
的名称是 myflags
那么在您的代码中:
std::vector<bool> myvector;
Flags myflags{ true,false,true};
Flags2 my2ndflags;
my2ndflags.flags = myflags;
for(int i = 0; i < 3; ++ i){
myvector.push_back(my2ndflags.flag[i]);
}
,
如何在 C++ 中迭代结构体?
与迭代任何没有预先存在的标准迭代器的方法相同:通过编写自定义迭代器。
编写自定义迭代器并不简单,编写这个自定义迭代器特别复杂,因为缺乏内省的语言特性,。一个不完整的简化示例:
struct Flags
{
bool isATrue;
bool isBTrue;
bool isCTrue;
struct iterator {
Flags* flags;
int index;
bool& operator*() {
switch(index) {
case 0: return flags->isATrue;
case 1: return flags->isBTrue;
case 2: return flags->isCTrue;
default: throw std::out_of_range("You wrote a bug!");
}
}
iterator& operator++() {
index++;
return *this;
}
iterator operator++(int) {
iterator next = *this;
index++;
return next;
}
friend auto operator<=>(const iterator&,const iterator&) = default;
};
iterator begin() {
return {this,0};
}
iterator end() {
return {this,3};
}
};
请注意,虽然可以在 C++ 中迭代类的成员,但这不一定有效。如果需要高效迭代,建议使用数组而不是类。