1. ホーム
  2. c++

[解決済み] コンパイル時の文字列ハッシュ化

2022-11-05 15:56:44

質問

C++11 の新しい文字列リテラルを使用すると、コンパイル時に文字列のハッシュを計算することができるかもしれない、という話をいくつかの場所で読みました。 しかし、誰もそれが可能であるとか、どのように行われるかを言い出す準備ができていないようです。

  • これは可能なのでしょうか。
  • 演算子はどのようなものでしょうか?

特にこのようなユースケースに興味があります。

void foo( const std::string& value )
{
   switch( std::hash(value) )
   {
      case "one"_hash: one(); break;
      case "two"_hash: two(); break;
      /*many more cases*/
      default: other(); break;
   }
}

注:コンパイル時のハッシュ関数は、私が書いたとおりに見える必要はありません。 私は最終的な解がどのようなものになるかを推測するために最善を尽くしましたが meta_hash<"string"_meta>::value も有効な解決策になり得ます。

どのように解決するのか?

今更ですが、コンパイル時のCRC32関数の実装に成功しました。 constexpr . 問題は、この記事を書いている時点では、GCCでしか動作せず、MSVCやIntelコンパイラでは動作しないことです。

以下はコードスニペットです。

// CRC32 Table (zlib polynomial)
static constexpr uint32_t crc_table[256] = {
    0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
    0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
    0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
...
};
template<size_t idx>
constexpr uint32_t crc32(const char * str)
{
    return (crc32<idx-1>(str) >> 8) ^ crc_table[(crc32<idx-1>(str) ^ str[idx]) & 0x000000FF];
}

// This is the stop-recursion function
template<>
constexpr uint32_t crc32<size_t(-1)>(const char * str)
{
    return 0xFFFFFFFF;
}

// This doesn't take into account the nul char
#define COMPILE_TIME_CRC32_STR(x) (crc32<sizeof(x) - 2>(x) ^ 0xFFFFFFFF)

enum TestEnum
{
    CrcVal01 = COMPILE_TIME_CRC32_STR("stack-overflow"),
};

CrcVal01 は 0x335CC04A と同じです。

これがあなたの助けになることを願っています。