3

0 ~ 255 の値に対して、事前計算されたビット カウント値 (数字の 1 ビットのカウント) を含む LUT を作成する必要があるとします。

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

ハードコーディングされた値を使用したくない場合は、適切なテンプレート ソリューションを使用できます。32 ビット整数で設定されたビット数をカウントするには?

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であることを知っています...

4

2 に答える 2

5

Boost.Preprocessor - 「外部コードジェネレーターを使用しない」に該当するかどうかはわかりません。


PP_ENUMバージョン

@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,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 ソリューション、特にそのような列挙型を見つけるのに苦労しました。TMP に対する PP の追加の重要な利点は、コンパイル時間です。

末尾のカンマについては、適切なコンパイラはすべてサポートする必要がありますが、サポートしていない場合は、繰り返し回数を 255 に変更し、最後のケースを手動で追加してください。

MACRO再定義の可能性を避けるために、意味のある名前に変更することもできます。

于 2013-07-24T11:05:46.770 に答える