我试图弄清楚如何在C ++(C ++ 11)的编译时生成一个预先计算的数组。
数组声明为unsigned char precalcalated_positions[256][8]
,而对于precalcalated_positions[x][y]
,给出第n + 1位的位位置(0-7),从字节值x或右边开始计数1位如果x
因此,例如,数组条目precalculated_positions[51][2]
将是4,因为51 = 00110011是二进制的,并且因为右边的第3(2 + 1)1位等于1 <&lt; 4。
虽然我可以很容易地编写一个程序来生成这个数组的源代码,但我想知道编译器本身是否有可能在编译时生成这个数组,也许是通过使用一些聪明的模板元编程和一些constexpr函数?
在运行时生成表的代码(未优化)如下:
int calculate_index(unsigned char c,unsigned char pos)
{
int mask = 1;
for(int i=0;i<8;i++) {
if (c&mask) {
if (pos==0) {
return i;
} else {
pos--;
}
}
mask<<=1;
}
return 8;
}
void generate_table() {
for(int i=0;i<256;i++) for(int j=0;j<8;j++) {
precalulated_positions[i][j] = calculate_index(i,j);
}
}
虽然真诚地感谢任何帮助,但请注意,这仅适用于C ++ 11。出于我的目的,我不能使用C ++ 14新的构造。
如果有任何不清楚的地方,请询问,我会尽量进一步详细说明。
答案 0 :(得分:2)
所以,我没有意识到你不能使用C ++ 14。我想出了另一个使用C ++ 11的解决方案。我在下面留下了C ++ 14代码。
我将您的算法转换为递归版本(以适应constexpr函数),并使用模板参数包填充表格。
template<int... Is>
struct Seq {};
template<int N, int... Is>
struct Gen : Gen<N-1, N-1, Is...> {};
template<int... Is>
struct Gen<0, Is...> : Seq<Is...> {};
constexpr auto computePosition(int c, int bit, int pos = 0) -> unsigned char {
return pos == 8 ?
8 :
(c & (1 << pos)) == 0 ?
computePosition(c, bit, pos+1) :
bit == 0 ?
pos :
computePosition(c, bit-1, pos+1);
}
template<int c, int... Is>
constexpr auto generatePositions(Seq<Is...>) -> std::array<unsigned char, 8> {
return {{ computePosition(c, Is)... }};
}
template<int c>
constexpr auto generatePositions() -> std::array<unsigned char, 8> {
return generatePositions<c>(Gen<8>{});
}
template<int... Is>
constexpr auto generateTable(Seq<Is...>) -> std::array<std::array<unsigned char, 8>, 256> {
return {{ generatePositions<Is>()... }};
}
constexpr auto generateTable() -> std::array<std::array<unsigned char, 8>, 256> {
return generateTable(Gen<256>{});
}
C ++ 14版本:
struct Table {
constexpr Table() : positions() {
for (auto c = 0; c < 256; ++c) {
for (auto i = 0; i < 8; ++i) {
int mask = 1;
auto pos = -1;
auto bit = i;
while (pos < 8 && bit >= 0) {
if (c & mask) {
--bit;
}
++pos;
mask <<= 1;
}
positions[c][i] = pos;
}
}
}
unsigned char positions[256][8];
};
int main()
{
constexpr auto precalculated_positions = Table();
static_assert(precalculated_positions.positions[51][2] == 4, "wrong");
}
值位于positions
类型的任何变量的Table
字段中。