2012-01-08 16 views
5

の一員として unordered_set私はメンバーとして、独自のタイプのunordered_setを持つクラスを書いています。 したがって、私は hash<Foo>の専門化を書く必要があります。この特殊化は、Fooが宣言された後に定義する必要があります。しかし、私はすでにメンバー unordered_set<Foo>を定義する前に hash<Foo>ための特殊化を必要とするかのように私には思えます。少なくともそれはコンパイルされず、そこでは失敗します。私はハッシュテンプレートの前方宣言を試みましたが、それによってそれを動作させることはできませんでした。 のstd :: Fooクラス

関連するコードスニペットは:予め

class Foo { 
public: 
    int i; 
    std::unordered_set<Foo> dummy; 
    Peer(std::unordered_set<Foo>); 
}; 

namespace std { 
    template<> struct hash<Foo> 
    { 
     size_t operator()(const Foo& f) const 
     { 
      return hash<int>()(f.i); 
     } 
    }; 
} 

おかげ

答えて

8
Foo

タイプstd::unordered_set<Foo>のメンバ変数を持つことはできません。

あなたは不完全な型で標準ライブラリコンテナをインスタンス化することはできません。基本的に、ここでは関係のないいくつかの例外を除いて、クラス定義はその定義を終了する}になるまで完了しません。

コンテナ内に別のタイプ(おそらくstd::unique_ptr<Foo>)を保存するか、コンテナに不完全なタイプのインスタンスを作成できるコンテナライブラリを使用する必要があります(Boostにはコンテナライブラリがあります)。

+0

速い答えのためのおかげで、私はいくつかの理由違っ – devmapal

+0

それを試してみましょう、クランは、この動作を許可します。 GCCは問題を正しく識別します。 – vmrob

1

あなたはそれをコンパイルするために少しの周りに宣言を移動することができます。

class Foo; 

namespace std { 
    template<> struct hash<Foo> { 
    size_t operator()(const Foo& f) const; 
    }; 
} 

class Foo { 
public: 
    int i; 
    std::unordered_set<Foo> dummy; 
    Foo(std::unordered_set<Foo>); 
}; 

namespace std { 
    size_t hash<Foo>::operator()(const Foo& f) const { 
    return hash<int>()(f.i); 
    } 
} 

をジェームズが言うように、しかし、dummyの宣言は未定義の動作です。

また、等価比較が必要になります。 operator==Fooに追加するのが最も簡単です。

私もFooのコンストラクタは、constの参照で引数を取る作ることをお勧めします。

+0

はい、コンパイルされます。しかし、それは実際にコンパイルされていないのでコンパイルしてはいけないので、このように使うべきではないでしょうか? – devmapal

+0

@devmapal:これは絶対に使用しないでください。私は、これが適用される将来の他のテンプレートシナリオを持っている場合にだけ投稿しました。問題は、標準では、標準ライブラリテンプレート*でこれをしてはいけないと言っていることだけです。あなたはそれが正しいことを証明することができればあなた自身のテンプレートでこれを行うことは自由です。 –

関連する問題