c – 在编译时生成BitCount LUT
假设我需要为0 … 255值创建一个包含预先计算的位计数值(数字中的1位数)的LUT:
int CB_LUT[256] = {0,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,255); // array declaration ... cout << CB_LUT[255]; // should print 8 笔记.这个问题不是关于计算一个数字中的1位,而是仅用作示例.我想在代码中完全生成这样的数组,而不使用外部代码生成器.必须在编译时生成数组. 编辑. #define MACRO(z,n,text) CountBits<8>(n) int CB_LUT[] = { BOOST_PP_ENUM(128,MACRO,_) }; #undef MACRO #define MACRO(z,text) CountBits<8>(n+128) int CB_LUT2[] = { BOOST_PP_ENUM(128,_) }; #undef MACRO for(int i = 0; i < 256; ++i) // use only CB_LUT { cout << CB_LUT[i] << endl; } 我知道这可能是UB …… 解决方法
使用宏(最近由我为我的代码重新发现)Boost.Preprocessor会很容易 – 我不确定它是否属于“不使用外部代码生成器”.
感谢@TemplateRex for BOOST_PP_ENUM,正如我所说,我对PP还不是很有经验:) #include <boost/preprocessor/repetition/enum.hpp> // with ENUM we don't need a comma at the end #define MACRO(z,text) CountBits<8>(n) int CB_LUT[256] = { BOOST_PP_ENUM(256,_) }; #undef MACRO 与PP_ENUM的主要区别在于它会在每个元素后自动添加逗号并删除最后一个元素.
#include <boost/preprocessor/repetition/repeat.hpp> #define MACRO(z,data) CountBits<8>(n),int CB_LUT[256] = { BOOST_PP_REPEAT(256,_) }; #undef MACRO 备注 它实际上非常简单易用,但由您来决定是否接受宏.我个人在使用Boost.MPL和模板技术方面苦苦挣扎,发现PP解决方案易于阅读,简短而强大,特别是对于那些枚举. PP相对于TMP的另一个重要优势是编译时间. 至于最后的逗号,所有合理的编译器应该支持它,但是如果你没有,只需将重复次数改为255并手动添加最后一个案例. 您可能还希望将MACRO重命名为有意义的内容,以避免可能的重新定义. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |