diff options
author | Paolo Carlini <paolo.carlini@oracle.com> | 2011-12-15 22:15:21 +0000 |
---|---|---|
committer | Paolo Carlini <paolo@gcc.gnu.org> | 2011-12-15 22:15:21 +0000 |
commit | 92637e93ed8cc9c607a6b544ed5944530ee99b03 (patch) | |
tree | e4fdba9c406221d03d29a59d8b97dba4ecb88f20 | |
parent | 5058651d6382e0f307f9c96c356cca2d41cbddba (diff) | |
download | gcc-92637e93ed8cc9c607a6b544ed5944530ee99b03.zip gcc-92637e93ed8cc9c607a6b544ed5944530ee99b03.tar.gz gcc-92637e93ed8cc9c607a6b544ed5944530ee99b03.tar.bz2 |
re PR libstdc++/51558 (Declaration of unspecialized std::hash<_Tp>::operator()(_Tp) turns compile-time errors into link-time errors)
2011-12-15 Paolo Carlini <paolo.carlini@oracle.com>
Jonathan Wakely <jwakely.gcc@gmail.com>
PR libstdc++/51558
* include/bits/functional_hash.h (struct hash): Add static_assert.
* src/compatibility-c++0x.cc: Adjust compatibility definitions.
* testsuite/23_containers/unordered_map/erase/51142.cc: Adjust.
* testsuite/23_containers/unordered_set/erase/51142.cc: Likewise.
* testsuite/23_containers/unordered_multimap/erase/51142.cc: Likewise.
* testsuite/23_containers/unordered_multiset/erase/51142.cc: Likewise.
Co-Authored-By: Jonathan Wakely <jwakely.gcc@gmail.com>
From-SVN: r182392
7 files changed, 75 insertions, 27 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 38e0ff2..f050ad9 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,14 @@ +2011-12-15 Paolo Carlini <paolo.carlini@oracle.com> + Jonathan Wakely <jwakely.gcc@gmail.com> + + PR libstdc++/51558 + * include/bits/functional_hash.h (struct hash): Add static_assert. + * src/compatibility-c++0x.cc: Adjust compatibility definitions. + * testsuite/23_containers/unordered_map/erase/51142.cc: Adjust. + * testsuite/23_containers/unordered_set/erase/51142.cc: Likewise. + * testsuite/23_containers/unordered_multimap/erase/51142.cc: Likewise. + * testsuite/23_containers/unordered_multiset/erase/51142.cc: Likewise. + 2011-12-15 Benjamin Kosnik <bkoz@redhat.com> * testsuite/22_locale/num_put/put/char/9780-2.cc: Add test for "C" diff --git a/libstdc++-v3/include/bits/functional_hash.h b/libstdc++-v3/include/bits/functional_hash.h index 2b82b21..e892159 100644 --- a/libstdc++-v3/include/bits/functional_hash.h +++ b/libstdc++-v3/include/bits/functional_hash.h @@ -57,8 +57,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> struct hash : public __hash_base<size_t, _Tp> { - size_t - operator()(_Tp __val) const; + static_assert(sizeof(_Tp) < 0, + "std::hash is not specialized for this type"); + size_t operator()(const _Tp&) const noexcept; }; /// Partial specializations for pointer types. diff --git a/libstdc++-v3/src/compatibility-c++0x.cc b/libstdc++-v3/src/compatibility-c++0x.cc index c5e1db0..03c58d2 100644 --- a/libstdc++-v3/src/compatibility-c++0x.cc +++ b/libstdc++-v3/src/compatibility-c++0x.cc @@ -52,36 +52,60 @@ namespace std _GLIBCXX_VISIBILITY(default) #ifndef _GLIBCXX_LONG_DOUBLE_COMPAT_IMPL template<> - size_t - hash<string>::operator()(string __s) const - { return _Hash_impl::hash(__s.data(), __s.length()); } + struct hash<string> + { + size_t operator()(string) const; + }; + + size_t + hash<string>::operator()(string __s) const + { return _Hash_impl::hash(__s.data(), __s.length()); } template<> - size_t - hash<const string&>::operator()(const string& __s) const - { return _Hash_impl::hash(__s.data(), __s.length()); } + struct hash<const string&> + { + size_t operator()(const string&) const; + }; + + size_t + hash<const string&>::operator()(const string& __s) const + { return _Hash_impl::hash(__s.data(), __s.length()); } #ifdef _GLIBCXX_USE_WCHAR_T template<> - size_t - hash<wstring>::operator()(wstring __s) const - { return _Hash_impl::hash(__s.data(), __s.length() * sizeof(wchar_t)); } + struct hash<wstring> + { + size_t operator()(wstring) const; + }; + + size_t + hash<wstring>::operator()(wstring __s) const + { return _Hash_impl::hash(__s.data(), __s.length() * sizeof(wchar_t)); } template<> - size_t - hash<const wstring&>::operator()(const wstring& __s) const - { return _Hash_impl::hash(__s.data(), __s.length() * sizeof(wchar_t)); } + struct hash<const wstring&> + { + size_t operator()(const wstring&) const; + }; + + size_t + hash<const wstring&>::operator()(const wstring& __s) const + { return _Hash_impl::hash(__s.data(), __s.length() * sizeof(wchar_t)); } #endif #endif template<> - size_t - hash<error_code>::operator()(error_code __e) const + struct hash<error_code> { - const size_t __tmp = std::_Hash_impl::hash(__e._M_value); - return std::_Hash_impl::__hash_combine(__e._M_cat, __tmp); - } + size_t operator()(error_code) const; + }; + size_t + hash<error_code>::operator()(error_code __e) const + { + const size_t __tmp = std::_Hash_impl::hash(__e._M_value); + return std::_Hash_impl::__hash_combine(__e._M_cat, __tmp); + } // gcc-4.7.0 // <chrono> changes is_monotonic to is_steady. diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/erase/51142.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/erase/51142.cc index eab637d..7986fb2 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_map/erase/51142.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_map/erase/51142.cc @@ -27,12 +27,15 @@ struct X X(T&) {} }; +struct X_hash +{ std::size_t operator()(const X&) const { return 0; } }; + bool operator==(const X&, const X&) { return false; } // LWG 2059. -void erasor(std::unordered_map<X, int>& s, X x) +void erasor(std::unordered_map<X, int, X_hash>& s, X x) { - std::unordered_map<X, int>::iterator it = s.find(x); + std::unordered_map<X, int, X_hash>::iterator it = s.find(x); if (it != s.end()) s.erase(it); } diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/erase/51142.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/erase/51142.cc index 678aa5d..0d434ac 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/erase/51142.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/erase/51142.cc @@ -27,12 +27,15 @@ struct X X(T&) {} }; +struct X_hash +{ std::size_t operator()(const X&) const { return 0; } }; + bool operator==(const X&, const X&) { return false; } // LWG 2059. -void erasor(std::unordered_multimap<X, int>& s, X x) +void erasor(std::unordered_multimap<X, int, X_hash>& s, X x) { - std::unordered_multimap<X, int>::iterator it = s.find(x); + std::unordered_multimap<X, int, X_hash>::iterator it = s.find(x); if (it != s.end()) s.erase(it); } diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/51142.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/51142.cc index 4db6af0..7a0a183 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/51142.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/51142.cc @@ -27,12 +27,15 @@ struct X X(T&) {} }; +struct X_hash +{ std::size_t operator()(const X&) const { return 0; } }; + bool operator==(const X&, const X&) { return false; } // LWG 2059. -void erasor(std::unordered_multiset<X>& s, X x) +void erasor(std::unordered_multiset<X, X_hash>& s, X x) { - std::unordered_multiset<X>::iterator it = s.find(x); + std::unordered_multiset<X, X_hash>::iterator it = s.find(x); if (it != s.end()) s.erase(it); } diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/erase/51142.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/erase/51142.cc index 1486460..ec5aeb1 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_set/erase/51142.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_set/erase/51142.cc @@ -27,12 +27,15 @@ struct X X(T&) {} }; +struct X_hash +{ std::size_t operator()(const X&) const { return 0; } }; + bool operator==(const X&, const X&) { return false; } // LWG 2059. -void erasor(std::unordered_set<X>& s, X x) +void erasor(std::unordered_set<X, X_hash>& s, X x) { - std::unordered_set<X>::iterator it = s.find(x); + std::unordered_set<X, X_hash>::iterator it = s.find(x); if (it != s.end()) s.erase(it); } |