diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2017-09-20 14:24:45 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2017-09-20 14:24:45 +0100 |
commit | f6b05c44aad49d8c37f4b3deaac93565126340f9 (patch) | |
tree | ad4f0a07abad59d603a2d3a532ece3c58c21f801 /libstdc++-v3 | |
parent | 3c16e99cf7731729290b96af4ec3b4fe6c68b63a (diff) | |
download | gcc-f6b05c44aad49d8c37f4b3deaac93565126340f9.zip gcc-f6b05c44aad49d8c37f4b3deaac93565126340f9.tar.gz gcc-f6b05c44aad49d8c37f4b3deaac93565126340f9.tar.bz2 |
PR libstdc++/82262 fix std::hash<std::optional<const T>>
PR libstdc++/82262
* include/std/optional (__optional_hash_call_base): Add template
parameter for remove_const_t<_Tp> and use it consistently.
* testsuite/20_util/optional/hash.cc: Test optional<const T>.
From-SVN: r253010
Diffstat (limited to 'libstdc++-v3')
-rw-r--r-- | libstdc++-v3/ChangeLog | 7 | ||||
-rw-r--r-- | libstdc++-v3/include/std/optional | 12 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/optional/hash.cc | 17 |
3 files changed, 26 insertions, 10 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index f9424a5..6c92731 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,10 @@ +2017-09-20 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/82262 + * include/std/optional (__optional_hash_call_base): Add template + parameter for remove_const_t<_Tp> and use it consistently. + * testsuite/20_util/optional/hash.cc: Test optional<const T>. + 2017-09-19 Jonathan Wakely <jwakely@redhat.com> PR libstdc++/71500 diff --git a/libstdc++-v3/include/std/optional b/libstdc++-v3/include/std/optional index 2743ef9..2df9b54 100644 --- a/libstdc++-v3/include/std/optional +++ b/libstdc++-v3/include/std/optional @@ -1005,23 +1005,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Hash. - template<typename _Tp, bool - = __poison_hash<remove_const_t<_Tp>>::__enable_hash_call> + template<typename _Tp, typename _Up = remove_const_t<_Tp>, + bool = __poison_hash<_Up>::__enable_hash_call> struct __optional_hash_call_base { size_t operator()(const optional<_Tp>& __t) const - noexcept(noexcept(hash<_Tp> {}(*__t))) + noexcept(noexcept(hash<_Up>{}(*__t))) { // We pick an arbitrary hash for disengaged optionals which hopefully // usual values of _Tp won't typically hash to. constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333); - return __t ? hash<_Tp> {}(*__t) : __magic_disengaged_hash; + return __t ? hash<_Up>{}(*__t) : __magic_disengaged_hash; } }; - template<typename _Tp> - struct __optional_hash_call_base<_Tp, false> {}; + template<typename _Tp, typename _Up> + struct __optional_hash_call_base<_Tp, _Up, false> {}; template<typename _Tp> struct hash<optional<_Tp>> diff --git a/libstdc++-v3/testsuite/20_util/optional/hash.cc b/libstdc++-v3/testsuite/20_util/optional/hash.cc index c16f0b2..35ae51b 100644 --- a/libstdc++-v3/testsuite/20_util/optional/hash.cc +++ b/libstdc++-v3/testsuite/20_util/optional/hash.cc @@ -29,14 +29,23 @@ template<class T> auto f(...) -> decltype(std::false_type()); static_assert(!decltype(f<S>(0))::value, ""); -static_assert(!std::is_invocable_v< - std::hash<std::optional<S>>&, std::optional<S> const&> ); -static_assert(std::is_invocable_v< - std::hash<std::optional<int>>&, std::optional<int> const&> ); + +template<typename T> +constexpr bool hashable() +{ return std::is_invocable_v<std::hash<T>&, const T&>; } + +static_assert(!hashable<std::optional<S>>()); +static_assert(!hashable<std::optional<const S>>()); +static_assert(hashable<std::optional<int>>()); +static_assert(hashable<std::optional<const int>>()); int main() { int x = 42; std::optional<int> x2 = 42; VERIFY(std::hash<int>()(x) == std::hash<std::optional<int>>()(x2)); + + // PR libstdc++/82262 + std::optional<const int> x3 = x2; + VERIFY(std::hash<int>()(x) == std::hash<std::optional<const int>>()(x3)); } |