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
This commit is contained in:
parent
3c16e99cf7
commit
f6b05c44aa
@ -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
|
||||
|
@ -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>>
|
||||
|
@ -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));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user