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";
}
GCCまたはClangでコンパイルされず、MSVCでコンパイルされない場合、MSVCは通常間違っています。 –
^MSVCは、標準に準拠したコードの解析において本質的に悪いことが知られています。 –
AFAIKこれは 'namespace std'を拡張することが禁じられています – alain