c++ - 在编译时生成 BitCount LUT

标签 c++ templates boost boost-preprocessor

假设我需要为 0...255 个值创建一个包含预先计算的位计数值(数字中 1 位的计数)的 LUT:

int CB_LUT[256] = {0, 1, 1, 2, ... 7, 8};

如果我不想使用硬编码值,我可以使用漂亮的模板解决方案 How to count the number of set bits in a 32-bit integer?

template <int BITS>
int CountBits(int val) 
{
    return (val & 0x1) + CountBits<BITS-1>(val >> 1);
}

template<>
int CountBits<1>(int val) 
{
    return val & 0x1;
}

int CB_LUT[256] = {CountBits<8>(0), CountBits<8>(1) ... CountBits<8>(255)}; 

这个数组是在编译时完全计算的。有没有办法避免长列表,并使用某种模板甚至宏(抱歉!)生成这样的数组,例如:

Generate(CB_LUT, 0, 255);  // array declaration
...
cout << CB_LUT[255];       // should print 8

注释。这个问题不是关于计算数字中的 1 位,它仅用作示例。我想在代码中完全生成这样的数组,而不使用外部代码生成器。数组必须在编译时生成。

编辑。 为了克服编译器限制,我找到了以下解决方案,基于 Bartek Banachewicz` 代码:

#define MACRO(z,n,text) CountBits<8>(n)
int CB_LUT[] = {
    BOOST_PP_ENUM(128, MACRO, _)
};
#undef MACRO

#define MACRO(z,n,text) CountBits<8>(n+128)
int CB_LUT2[] = {
    BOOST_PP_ENUM(128, MACRO, _)
};
#undef MACRO

for(int i = 0; i < 256; ++i)   // use only CB_LUT
{
    cout << CB_LUT[i] << endl;
}

我知道这可能是UB...

最佳答案

使用宏(我最近为我的代码重新发现)Boost.Preprocessor 会相当容易 - 我不确定它是否属于“不使用外部代码生成器”。


PP_ENUM版本

感谢@TemplateRex BOOST_PP_ENUM,正如我所说,我在 PP 方面还不是很有经验 :)

#include <boost/preprocessor/repetition/enum.hpp>

// with ENUM we don't need a comma at the end
#define MACRO(z,n,text) CountBits<8>(n)
int CB_LUT[256] = {
    BOOST_PP_ENUM(256, MACRO, _)
};
#undef MACRO

PP_ENUM 的主要区别在于它会自动在每个元素后添加逗号并去掉最后一个。


PP_REPEAT版本

#include <boost/preprocessor/repetition/repeat.hpp>
 
#define MACRO(z,n,data) CountBits<8>(n),
int CB_LUT[256] = {    
    BOOST_PP_REPEAT(256, MACRO, _)
};
#undef MACRO

备注

它实际上非常简单易用,但是否接受宏由您决定。我个人一直在努力使用 Boost.MPL 和模板技术,以找到易于阅读、简短而强大的 PP 解决方案,尤其是对于像这样的枚举。 PP 相对于 TMP 的另一个重要优势是编译时间。

至于末尾的逗号,所有合理的编译器都应该支持它,但如果您的编译器不支持,只需将重复次数更改为 255 并手动添加最后一个大小写即可。

您可能还想将 MACRO 重命名为有意义的名称以避免可能的重新定义。

关于c++ - 在编译时生成 BitCount LUT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17831460/

相关文章:

c++ - .exe 不显示 "Press any key to continue..."

c++ - 是否可以在 C++ 中调用导出的 "private"方法

visual-studio - MSVS : How can I set the x64 as the default, 而不是 AnyCPU?

c++ - 使用条件变量的单生产者多消费者缓冲区 pthread 实现

c++ - 最简单最整洁的c++11 ScopeGuard

c++ - 模板参数列表太少问题

python - 包含后的 Jinja2 编译扩展

c++ - 在生产者-消费者情况下使用条件变量

c++ - 在没有正则表达式的情况下验证电子邮件地址

c++ - 编译时vscode找不到 header ,而Intellisense可以