2017-12-14 4 views
3

リテラル文字列が指定されている場合はコンパイル時に文字列ハッシングを実行するクラスを実装しようとしています(実行時(this articleに基づく))。 私はxxHash(64ビット)のようにFNV-1aを使用していませんが、コンパイル時にはthis codeを使用しています。VS15はconstexprと文字列リテラルでC2975をスローします

は、ここに私の実装です:

class StringHash { 
public: 
    class ConstCharWrapper { 
    public: 
     inline ConstCharWrapper(const char *Str) : Internal(Str) {} 
     const char *Internal; 
    }; 

template <size_t N> 
__forceinline StringHash(const char (&Str)[N]) : 
    m_Hash(std::integral_constant<uint64_t, xxh64::hash(Str, N-1)>::value) 
{ 
} 

inline StringHash(ConstCharWrapper Str) : 
    m_Hash(xxHash_64::Calc((const uint8_t*)Str.Internal, strlen(Str.Internal))) 
{ 
} 

inline StringHash(const char *Str, size_t Length) : 
    m_Hash(xxHash_64::Calc((const uint8_t*)Str, Length)) 
{ 
} 

__forceinline operator uint64_t() const { return m_Hash; } 

private: 
    const uint64_t m_Hash; 
}; 

リテラル文字列が正しくテンプレートコンストラクタに派遣されているが、私はハッシュが完全にコンパイル時に計算されなかったことを、生成されたアセンブリを見ることで、気づきました。

私はstd::integral_constantを使用してコンパイル時にコンパイルを強制しましたが、今はC2975エラー('_Val' : invalid template argument for 'std::integral_constant', expected compile-time constant expression)が発生しています。問題は、何ができるかを把握しよう、私はテンプレートのコンストラクタに直接ハードコードされた文字列を入れてみました

template <size_t N> 
__forceinline StringHash(const char (&Str)[N]) : 
    m_Hash(std::integral_constant<uint64_t, xxHash_CT::h64("foobar", 6)>::value) 
{ 
} 

そして、それがうまく働いた... 私は見当もつかない何が問題なのか、あなたの助けをありがとう。

答えて

5

問題はここでは、次のとおりです。

template <size_t N> 
__forceinline StringHash(const char (&Str)[N]) : 
    m_Hash(std::integral_constant<uint64_t, xxh64::hash(Str, N-1)>::value) 
//              ^^^^^^ 
{ 
} 

Strは定数式(関数のパラメータは、定数式ではないので)ではありませんので、あなたは定数式としてhash()の結果を使用することはできません。この作業をするには、進行中の作業である文字列リテラルテンプレートパラメータを持つ必要があります(P0424)。

の定数式であるため、他の例が有効です。

+0

ありがとうございます。回避策または同様の機能を実現する別の方法がありますか? – Spacebrain

+1

@Spacebrainコンパイル時の文字列処理ですか?あなたは手動で型をエンコードする必要があります... 'struct X {static constexpr const char * value =" hello "; }; ' – Barry

+0

ありがとう、私はこれを解決しようとする:) – Spacebrain

関連する問題