从整数数组构造 bitset

Construct bitset from array of integers

uint64_t 构造 bitset<64> 很容易:

uint64_t flags = ...;
std::bitset<64> bs{flags};

但是有没有一种好方法可以从 uint64_t[N] 构造一个 bitset<64 * N>,这样 flags[0] 将引用最低的 64 位?

uint64_t flags[3];
// ... some assignments
std::bitset<192> bs{flags};  // this very unhelpfully compiles
                             // yet is totally invalid

还是我必须循环调用 set()

std::bitset 没有范围构造函数,因此您将不得不循环,但是用 std::bitset::set() 单独设置每一位是不够的。 std::bitset 支持二进制运算符,因此您至少可以批量设置 64 位:

  std::bitset<192> bs;

  for(int i = 2; i >= 0; --i) {
    bs <<= 64;
    bs |= flags[i];
  }

更新: 在评论中,@icando 提出了有效的担忧,即移位是 std::bitset 的 O(N) 操作。对于非常大的位集,这最终会消耗批量处理的性能提升。在我的基准测试中,与单独设置位且不改变输入数据的简单循环相比,std::bitset<N * 64> 的盈亏平衡点:

int pos = 0;
for(auto f : flags) {
  for(int b = 0; b < 64; ++b) {
    bs.set(pos++, f >> b & 1);
  }
}

大约在 N == 200 附近(x86-64 上的 gcc 4.9,带有 libstdc++ 和 -O2)。 Clang 的表现稍差,在 N == 160 左右收支平衡。 -O3 的 Gcc 将其推到 N == 250.

取下端,这意味着 如果你想使用 10000 位或更大的位集,这种方法可能不适合你。 在 32 位平台上 (例如常见的 ARM),阈值可能会更低,因此在此类平台上使用 5000 位位集时请记住这一点。然而,我认为,在这之前的某个地方,您应该问问自己,bitset 是否真的是容器的正确选择。

如果从范围初始化很重要,您可以考虑使用 std::vector

它确实有一对迭代器的构造函数