c++ - 在编译时初始化非常大的 C++ std::bitset
问题描述
我想存储一个 2 16位的静态常量位集,其中包含永远不会改变的 1 和 0 的特定序列。
我想过使用这篇文章提出的初始化字符串:
std::bitset<1<<16> myBitset("101100101000110 ... "); // the ellipsis are replaced by the actual 65536-character sequence
但是编译器(VS2013)给了我“字符串太长”的错误。
更新
我尝试按照上面链接的帖子中的建议将字符串拆分成更小的块,如下所示:
std::bitset<1<<16> myBitset("100101 ..."
"011001 ..."
...
);
但我收到错误C1091: compiler limit: string exceeded 65535 bytes in length。我的字符串是 65536 字节(技术上是 65537,带有 EOS 字符)。
我还有哪些其他选择?
更新
感谢luk32,这是我最终得到的漂亮代码:
const std::bitset<1<<16> bs = (std::bitset<1<<16>("101011...")
<< 7* (1<<13)) | (std::bitset<1<<16>("110011...")
<< 6* (1<<13)) | (std::bitset<1<<16>("101111...")
<< 5* (1<<13)) | (std::bitset<1<<16>("110110...")
<< 4* (1<<13)) | (std::bitset<1<<16>("011011...")
<< 3* (1<<13)) | (std::bitset<1<<16>("111011...")
<< 2* (1<<13)) | (std::bitset<1<<16>("111001...")
<< 1* (1<<13)) | std::bitset<1<<16>("1100111...");
解决方案
您并没有真正拆分文字。无论如何,它都会被连接起来进行编译。您受到编译器的限制。我认为没有办法在 MSVC 中增加这个限制。
您可以将其拆分为两个文字,初始化两个位集,移动第一部分和OR
另一个。
就像是:
#include <iostream>
#include <string>
#include <bitset>
using namespace std;
int main()
{
std::bitset<8> dest("0110");
std::bitset<8> lowBits("1001");
dest <<= dest.size()/2;
dest |= lowBits;
std::cout << dest << '\n';
}
如果您查看clang 编译器的输出-02
105
,它会被优化为加载01101001
.
我的测试表明,如果您使用 SSE 交换8
它1<<16
,那么它应该是非常安全的选择。它并没有像8
or那样丢弃文字16
,因此可能会有一些运行时开销,但我不确定您是否可以做得更好。
编辑:
我做了更多测试,这是我的游乐场:
#include <iostream>
#include <string>
#include <bitset>
using namespace std;
int main()
{
//static const std::bitset<16> set1( "01100110011001100110011001100110");
static const std::bitset<16> set2(0b01100110011001100110011001100110);
static const std::bitset<16> high(0b01100110);
static const std::bitset<16> low (0b01100110);
static const std::bitset<16> set3 = (high << 8) | low;
std::cout << (set3 == set2) << '\n';
}
const char*
除了clang,我无法在任何编译器上对构造函数进行编译时优化,并且最多可以使用14个字符。如果您将一堆bitset
s 初始化unsigned long long
并 shift 并将它们组合在一起,似乎会有一些承诺:
static const std::bitset<128> high(0b0110011001100110011001100110011001100110011001100110011001100110);
static const std::bitset<128> low (0b1001100110011001100110011001100110011001100110011001100110011001);
static const std::bitset<128> set3 = (high << high.size()/2) | low;
std::cout << set3 << '\n';
这使得编译器坚持二进制数据存储。如果可以使用更新的编译器,constexpr
我认为可以将其声明为bitset
从 s 构造的ull
s 数组,并通过函数将它们连接起来constexpr
并绑定到constexpr const
变量,这应该可以确保最佳优化。编译器仍然可能对你不利,但没有理由。也许即使没有constexpr
它也会生成非常优化的代码。
推荐阅读
- java - Maven 编译器未将 getter/setter(使用 Lombok 生成)添加到构建 jar 文件
- jquery - 在菜单中添加活动类
- javascript - React .setState() 中的扩展运算符
- java - Java 9 Stream iterate 方法忽略流的最后一个元素
- laravel - Laravel 的 Spark 'teamSubscribed' 中间件与 freeTeamPlan 的问题
- gitlab - 电子更新程序无法解析 gitlab 私有仓库的工件中的 latest.yml
- c - 如何检查输入的符号是否为char?
- java - 如何确定一个 int 是否是完美的正方形?
- java - O(n)中数组的查找模式
- java - 如何使用 JWebBrowser 禁用 PDF 打印选项