生成表,指示编译时字节中第n位的位置

时间:2016-08-12 18:09:57

标签: arrays c++11 compile-time

我试图弄清楚如何在C ++(C ++ 11)的编译时生成一个预先计算的数组。

数组声明为unsigned char precalcalated_positions[256][8],而对于precalcalated_positions[x][y],给出第n + 1位的位位置(0-7),从字节值x或右边开始计数1位如果x

中没有那么多的1位,则为8

因此,例如,数组条目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新的构造。

如果有任何不清楚的地方,请询问,我会尽量进一步详细说明。

1 个答案:

答案 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>{});
}

Live example

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字段中。

Live example