2016-08-05 8 views
5

なぜ前方宣言を次のように前方宣言::ハッシュテンプレートの特殊

template<typename T> struct std::hash; 

はgccと打ち鳴らすとコンパイルに失敗しますが、Visual Studioの2015でコンパイル? (coliruを使用して)

のgcc 6.1.0:

main.cpp:11:34: error: invalid use of template-name 'std::hash' without an argument list 
template<typename T> struct std::hash; 
            ^~~~ 

(coliruを使用して)打ち鳴らす3.8.0:

main.cpp:11:29: error: forward declaration of struct cannot have a nested name specifier 
template<typename T> struct std::hash; 
          ^~~~~ 

それはVS(http://webcompiler.cloudapp.net/)の下で動作します。どのコンパイラが正しいのですか?

btw。 C++ Primer 5th editionでも同じ宣言が使用されています。まあ、ほぼ同じそれstructの代わりにclassを使用して:template <class T> class std::hash;間違っています。

フルコード:前方宣言はずっと通常の宣言のように機能しなければならないので

#include <unordered_map> 

/* 
// compiles with gcc,clang,VS 
namespace std { 
    template<typename T> 
    struct hash; 
}*/ 

// Compiles only with VS 
template<typename T> struct std::hash; 

struct MyData { 
    MyData() {} 
    MyData(int d1, int d2) : data1(d1), data2(d2) {} 
    bool operator==(const MyData& rop) const { 
    return rop.data1 == data1 && rop.data2 == data2; 
    } 

    friend struct std::hash<MyData>; 
private: 
    int data1; 
    int data2; 
}; 

namespace std { 
    template<> 
    struct hash<MyData> { 
    typedef MyData argument_type; 
    typedef size_t result_type; 
    size_t operator()(const argument_type& data) const noexcept; 
    }; 

    size_t hash<MyData>::operator()(const argument_type& data) const noexcept { 
    return hash<unsigned>()(data.data1)^hash<unsigned>()(data.data2); 
    } 
} 

int main() { 
    std::unordered_map<MyData, std::string> mm; 
    mm[MyData(1,1)] = "test1"; 
    mm[MyData(2,2)] = "test1"; 
} 
+4

GCCまたはClangでコンパイルされず、MSVCでコンパイルされない場合、MSVCは通常間違っています。 –

+0

^MSVCは、標準に準拠したコードの解析において本質的に悪いことが知られています。 –

+0

AFAIKこれは 'namespace std'を拡張することが禁じられています – alain

答えて

1

理由は、大部分のようです。すなわち、名前空間に入れられ、接頭辞は1ではない。私はこれが、同じパーサが宣言と前方宣言に使用されることを可能にすると思う。