10

オブジェクトのハッシュ関数を作成しています。Generic Hash function for all STL-containers のおかげで、すでにコンテナーをハッシュし、ハッシュを組み合わせることができます。しかし、私のクラスには列挙型もあります。もちろん、すべての列挙型に対してハッシュ関数を作成することはできますが、それは良い考えではないようです。の一般的な仕様を作成してstd::hash、すべての列挙型に適用できるようにすることは可能ですか? とを使用して、そのようなstd::enable_ifものstd::is_enum

namespace std {
  template <class E>
  class hash<typename std::enable_if<std::is_enum<E>::value, E>::type> {
  public:
    size_t operator()( const E& e ) const {
      return std::hash<std::underlying_type<E>::type>()( e );
    }
  };
};

PS。このコードはコンパイルされません

error: template parameters not used in partial specialization:
error:         ‘E’
4

3 に答える 3

11

コンパイラーは、あなたが再び意味するEことになることを知ることができないため、パラメーターを推測することはできません(実際、設計上、それを行わない特殊化がいくつかあります!)。の「非推定コンテキスト」と呼ばれます。enable_if<...>::typeEE

パラメーターが 1 つしかない場合hash、(私が認識している) SFINAE で部分的な特殊化を行う方法はありません。

于 2012-03-10T12:14:34.907 に答える
4

マクロを使用する場合は、正しい std::hash 特殊化を enum 宣言の隣にダンプできます。

それ以外の場合、enum 値を簡単にハッシュする唯一の方法は、ハッシュ タイプを一般化することです。

struct enum_hash
{
    template <typename T>
    inline
    typename std::enable_if<std::is_enum<T>::value, std::size_t>::type
    operator ()(T const value) const
    {
        return static_cast<std::size_t>(value);
    }
};

そしてそれをそのように使用する:

enum class E { a, b, c };
std::unordered_map<E, std:string, enum_hash> map;
map[E::a] = "a";
于 2013-07-12T19:17:58.137 に答える
2

あなたがやろうとしていることは、標準で禁止されています。

[名前空間.std]

別段の指定がない限り、名前空間 std または名前空間 std 内の名前空間に宣言または定義を追加する場合、C++ プログラムの動作は未定義です。

プログラムは、宣言がユーザー定義型に依存し、特殊化が元のテンプレートの標準ライブラリ要件を満たし、明示的に禁止されていない場合にのみ、標準ライブラリ テンプレートのテンプレート特殊化を名前空間 std に追加できます。

したがって、これらの回答のいくつかのアイデアを確かに追求することはできますが、それを std::hash と呼ぶことはできません。独自の「enum_hash」テンプレートを定義することは良い考えのようです。

于 2014-04-26T14:01:02.900 に答える