aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2017-09-20 14:24:45 +0100
committerJonathan Wakely <redi@gcc.gnu.org>2017-09-20 14:24:45 +0100
commitf6b05c44aad49d8c37f4b3deaac93565126340f9 (patch)
treead4f0a07abad59d603a2d3a532ece3c58c21f801
parent3c16e99cf7731729290b96af4ec3b4fe6c68b63a (diff)
downloadgcc-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
-rw-r--r--libstdc++-v3/ChangeLog7
-rw-r--r--libstdc++-v3/include/std/optional12
-rw-r--r--libstdc++-v3/testsuite/20_util/optional/hash.cc17
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));
}