У меня есть собственная реализация класса bitset в C ++. Я часто перебираю индексы битов, которые установлены в наборе битов (т.е. для набора битов '10011' я хочу перебирать числа 0, 3, 4.) Эта итерация может быть реализована следующим образом:
struct Bitset {
uint64_t* data_;
size_t chunks_;
std::vector<int> Elements() const {
std::vector<int> ret;
for (size_t i=0;i<chunks_;i++){
uint64_t td = data_[i];
while (td) {
ret.push_back(i*BITS + __builtin_ctzll(td));
td &= ~-td;
}
}
return ret;
}
};
void Iterate(Bitset bitset) {
for (int b : bitset.Elements()) {
std::cout << "bit: " << b << std::endl;
}
}
Приведенная выше реализация обеспечивает чистый код для итерации, но включает в себя ненужное выделение кучи с вектором. Следующая версия, которая, по сути, содержит функцию Elements (), часто работает быстрее:
void Iterate(Bitset bitset) {
int chunks = bitset.chunks_;
for (int i = 0; i < chunks; i++) {
uint64_t td = bitset.data_[i];
while (td) {
std::cout << "bit: " << i*BITS + __builtin_ctzll(td) << std::endl;
td &= ~-td;
}
}
}
Какой хороший способ реализовать абстракцию для итерации, чтобы она была такой же чистой, как и в приведенной выше версии, но также без затрат на производительность.