2016-05-18 12 views
0

通常、新しいタイプにハッシュが必要な場合は、std::hashを特殊化する必要があります。私はテストハッシュライブラリを書いていて、標準ライブラリではまだ特化されていないすべての型に対してそれを使いたいと思っています。std :: hashテンプレート構造体の再定義

gcc/4.9.3とclang/3.7.0で次のように試しました。私の驚きには、それは動作します。

#include <utility> 
#include <functional> 
#include <iostream> 

namespace std { 

template<typename T> 
class hash 
{ 
    public: 
     size_t operator()(const T & obj) 
     { 
      return 99; 
     } 
}; 
} 

int main(void) 
{ 
    int i = 10; 
    std::pair<int, int> pi{22,33}; 

    std::hash<int> hi; 
    std::hash<std::pair<int, int>> hpi; 

    std::cout << "Hash of int: " << hi(i) << "\n"; 
    std::cout << "Hash of int pair: " << hpi(pi) << "\n"; 
    return 0; 
} 

整数のハッシュは(標準ライブラリバージョンである)整数自体であり、一対のハッシュは、99

ように、2つの質問です。

  1. なぜ機能しますか? std::hashのテンプレートバージョンは既に宣言されているはずです。 (私の推測では、それはより深い名前空間にあり、転送されます)

  2. これは標準的な動作ですか?

編集:質問1 - template<typename T> struct hashへの回答は宣言されていますが、どこにも定義されていないようです。だから私はそれを定義することができます。

+3

未定義の動作には、通常どおり、「動作しています」が含まれます。 –

+0

@ T.C。したがって、これが定義された動作であるかどうかを知りたがっています... –

答えて

1

17.6.4.2.1名前空間std [namespace.std]

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

すでに存在する一般テンプレートをnamespace stdに再定義したため、未定義の動作が発生します。それは@ T.Cのようになります。コメントには、プログラムが正常に動作することが記載されています。

+1

私は、私が何かを(ODRに違反し、コンパイルすべきではない)再定義していると思ったので私の最初の混乱がありました。私は実際に定義を追加していますが、それでもこの規則に違反しています。 (そして、はい、私は、未定義の振る舞いが時にはうまくいくかもしれないことをよく知っています)。 –

関連する問題