* Allows conversion from a deleter for objects of another type, `_Up`,
* only if `_Up*` is convertible to `_Tp*`.
*/
- template<typename _Up, typename = typename
- enable_if<is_convertible<_Up*, _Tp*>::value>::type>
+ template<typename _Up,
+ typename = _Require<is_convertible<_Up*, _Tp*>>>
default_delete(const default_delete<_Up>&) noexcept { }
/// Calls `delete __ptr`
* it is undefined to `delete[]` an array of derived types through a
* pointer to the base type.
*/
- template<typename _Up, typename = typename
- enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type>
+ template<typename _Up,
+ typename = _Require<is_convertible<_Up(*)[], _Tp(*)[]>>>
default_delete(const default_delete<_Up[]>&) noexcept { }
/// Calls `delete[] __ptr`
template<typename _Up>
- typename enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type
+ typename enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type
operator()(_Up* __ptr) const
- {
- static_assert(sizeof(_Tp)>0,
- "can't delete pointer to incomplete type");
- delete [] __ptr;
- }
+ {
+ static_assert(sizeof(_Tp)>0,
+ "can't delete pointer to incomplete type");
+ delete [] __ptr;
+ }
};
/// @cond undocumented
unique_ptr<_Tp, _Dp>&) = delete;
#endif
- /// Equality operator for unique_ptr objects, compares the owned pointers.
+ /// Equality operator for unique_ptr objects, compares the owned pointers
template<typename _Tp, typename _Dp,
typename _Up, typename _Ep>
_GLIBCXX_NODISCARD inline bool
_GLIBCXX_NODISCARD inline bool
operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
{ return !(nullptr < __x); }
+ // @} relates unique_ptr
+
+ /// @cond undocumented
+ template<typename _Up, typename _Ptr = typename _Up::pointer,
+ bool = __poison_hash<_Ptr>::__enable_hash_call>
+ struct __uniq_ptr_hash
+#if ! _GLIBCXX_INLINE_VERSION
+ : private __poison_hash<_Ptr>
+#endif
+ {
+ size_t
+ operator()(const _Up& __u) const
+ noexcept(noexcept(std::declval<hash<_Ptr>>()(std::declval<_Ptr>())))
+ { return hash<_Ptr>()(__u.get()); }
+ };
+
+ template<typename _Up, typename _Ptr>
+ struct __uniq_ptr_hash<_Up, _Ptr, false>
+ : private __poison_hash<_Ptr>
+ { };
+ /// @endcond
/// std::hash specialization for unique_ptr.
template<typename _Tp, typename _Dp>
struct hash<unique_ptr<_Tp, _Dp>>
: public __hash_base<size_t, unique_ptr<_Tp, _Dp>>,
- private __poison_hash<typename unique_ptr<_Tp, _Dp>::pointer>
- {
- size_t
- operator()(const unique_ptr<_Tp, _Dp>& __u) const noexcept
- {
- typedef unique_ptr<_Tp, _Dp> _UP;
- return std::hash<typename _UP::pointer>()(__u.get());
- }
- };
+ public __uniq_ptr_hash<unique_ptr<_Tp, _Dp>>
+ { };
#if __cplusplus > 201103L
-
+ /// @relates unique_ptr @{
#define __cpp_lib_make_unique 201304
/// @cond undocumented
template<typename _Tp, typename... _Args>
inline typename _MakeUniq<_Tp>::__invalid_type
make_unique(_Args&&...) = delete;
+ // @} relates unique_ptr
#endif
- // @} relates unique_ptr
// @} group pointer_abstractions
#if __cplusplus >= 201703L
--- /dev/null
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++11 } }
+
+#include <memory>
+
+template<typename Func, typename Arg, typename = void>
+ struct is_callable
+ : std::false_type
+ { };
+
+template<typename Func, typename Arg>
+ struct is_callable<Func, Arg,
+ decltype((void)(std::declval<Func&>()(std::declval<Arg>())))>
+ : std::true_type
+ { };
+
+void
+test01()
+{
+ struct D {
+ struct pointer { };
+ void operator()(pointer) const noexcept { }
+ };
+ static_assert( !is_callable<std::hash<D::pointer>&, D::pointer>::value );
+
+ using UP = std::unique_ptr<int, D>;
+ // [unord.hash]
+ // Disabled specializations of hash are not function object types
+ static_assert( !is_callable<std::hash<UP>&, UP>::value );
+ static_assert( !is_callable<std::hash<UP>&, UP&>::value );
+ static_assert( !is_callable<std::hash<UP>&, const UP&>::value );
+}
+
+struct D {
+ struct pointer { };
+ void operator()(pointer) const noexcept { }
+};
+
+bool operator==(D::pointer, std::nullptr_t) { return false; }
+bool operator!=(D::pointer, std::nullptr_t) { return true; }
+
+namespace std {
+ template<> struct hash<D::pointer> {
+ size_t operator()(D::pointer) const { throw 1; }
+ };
+}
+
+void
+test02()
+{
+ using UP = std::unique_ptr<int, D>;
+ UP p;
+ std::hash<UP> h;
+ try {
+ // [util.smartptr.hash]
+ // The member functions are not guaranteed to be noexcept.
+ h(p);
+ throw "should not reach here";
+ } catch (int) {
+ // Should catch exception here, rather than terminating.
+ }
+
+ // Should still be noexcept if the underlying hash object is:
+ using UP2 = std::unique_ptr<int>;
+ UP2 p2;
+ std::hash<UP2> h2;
+ static_assert( noexcept(h2(p2)), "operator() is noexcept" );
+}
+
+int
+main()
+{
+ test02();
+}