Commit f6b05c44 by Jonathan Wakely Committed by Jonathan Wakely

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
parent 3c16e99c
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> 2017-09-19 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/71500 PR libstdc++/71500
......
...@@ -1005,23 +1005,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -1005,23 +1005,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Hash. // Hash.
template<typename _Tp, bool template<typename _Tp, typename _Up = remove_const_t<_Tp>,
= __poison_hash<remove_const_t<_Tp>>::__enable_hash_call> bool = __poison_hash<_Up>::__enable_hash_call>
struct __optional_hash_call_base struct __optional_hash_call_base
{ {
size_t size_t
operator()(const optional<_Tp>& __t) const 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 // We pick an arbitrary hash for disengaged optionals which hopefully
// usual values of _Tp won't typically hash to. // usual values of _Tp won't typically hash to.
constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333); 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> template<typename _Tp, typename _Up>
struct __optional_hash_call_base<_Tp, false> {}; struct __optional_hash_call_base<_Tp, _Up, false> {};
template<typename _Tp> template<typename _Tp>
struct hash<optional<_Tp>> struct hash<optional<_Tp>>
......
...@@ -29,14 +29,23 @@ template<class T> ...@@ -29,14 +29,23 @@ template<class T>
auto f(...) -> decltype(std::false_type()); auto f(...) -> decltype(std::false_type());
static_assert(!decltype(f<S>(0))::value, ""); static_assert(!decltype(f<S>(0))::value, "");
static_assert(!std::is_invocable_v<
std::hash<std::optional<S>>&, std::optional<S> const&> ); template<typename T>
static_assert(std::is_invocable_v< constexpr bool hashable()
std::hash<std::optional<int>>&, std::optional<int> const&> ); { 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 main()
{ {
int x = 42; int x = 42;
std::optional<int> x2 = 42; std::optional<int> x2 = 42;
VERIFY(std::hash<int>()(x) == std::hash<std::optional<int>>()(x2)); 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));
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment