diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index f7ea9285cc0..e87c303d47b 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,17 @@ 2015-07-01 Jonathan Wakely + * include/bits/alloc_traits.h (__alloctr_rebind): Remove. + (__allocator_traits_base): New base class. + (__alloc_rebind): Reimplement in terms of detection idiom. + (allocator_traits): Derive from __allocator_traits_base. Reimplement + nested types in terms of detection idiom. Simplify SFINAE constraints + on overloaded static member functions. + * include/bits/hashtable.h (_Hashtable): Use __alloc_rebind instead + of __alloctr_rebind. + * testsuite/20_util/scoped_allocator/propagation.cc: Define rebind. + * testsuite/23_containers/unordered_set/instantiation_neg.cc: Adjust + dg-error line number. + * include/bits/ptr_traits.h (__ptrtr_elt_type, __ptrtr_diff_type, __ptrtr_rebind, __ptrtr_not_void): Remove (__get_first_arg, __replace_first_arg, __make_not_void): Define new diff --git a/libstdc++-v3/include/bits/alloc_traits.h b/libstdc++-v3/include/bits/alloc_traits.h index bb98c1d4ce8..e5ed92b9e29 100644 --- a/libstdc++-v3/include/bits/alloc_traits.h +++ b/libstdc++-v3/include/bits/alloc_traits.h @@ -40,72 +40,57 @@ namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION - template - class __alloctr_rebind_helper - { - template - static constexpr true_type - _S_chk(typename _Alloc2::template rebind<_Tp2>::other*); + struct __allocator_traits_base + { + template + using __rebind = typename _Alloc::template rebind<_Up>::other; - template - static constexpr false_type - _S_chk(...); + protected: + template + using __pointer = typename _Tp::pointer; + template + using __c_pointer = typename _Tp::const_pointer; + template + using __v_pointer = typename _Tp::void_pointer; + template + using __cv_pointer = typename _Tp::const_void_pointer; + template + using __diff_type = typename _Tp::difference_type; + template + using __size_type = typename _Tp::size_type; + template + using __pocca = typename _Tp::propagate_on_container_copy_assignment; + template + using __pocma = typename _Tp::propagate_on_container_move_assignment; + template + using __pocs = typename _Tp::propagate_on_container_swap; + template + using __equal = typename _Tp::is_always_equal; + }; - public: - using __type = decltype(_S_chk<_Alloc, _Tp>(nullptr)); - }; - - template::__type::value> - struct __alloctr_rebind; - - template - struct __alloctr_rebind<_Alloc, _Tp, true> - { - typedef typename _Alloc::template rebind<_Tp>::other __type; - }; - - template class _Alloc, typename _Tp, - typename _Up, typename... _Args> - struct __alloctr_rebind<_Alloc<_Up, _Args...>, _Tp, false> - { - typedef _Alloc<_Tp, _Args...> __type; - }; - - template - using __alloc_rebind = typename __alloctr_rebind<_Alloc, _Tp>::__type; + template + using __alloc_rebind = __detected_or_t_<__replace_first_arg_t, + __allocator_traits_base::__rebind, + _Alloc, _Up>; /** * @brief Uniform interface to all allocator types. * @ingroup allocators */ template - struct allocator_traits + struct allocator_traits : __allocator_traits_base { /// The allocator type typedef _Alloc allocator_type; /// The allocated type typedef typename _Alloc::value_type value_type; -#define _GLIBCXX_ALLOC_TR_NESTED_TYPE(_NTYPE, _ALT) \ - private: \ - template \ - static typename _Tp::_NTYPE _S_##_NTYPE##_helper(_Tp*); \ - static _ALT _S_##_NTYPE##_helper(...); \ - typedef decltype(_S_##_NTYPE##_helper((_Alloc*)0)) __##_NTYPE; \ - public: - -_GLIBCXX_ALLOC_TR_NESTED_TYPE(pointer, value_type*) - /** * @brief The allocator's pointer type. * * @c Alloc::pointer if that type exists, otherwise @c value_type* */ - typedef __pointer pointer; - -_GLIBCXX_ALLOC_TR_NESTED_TYPE(const_pointer, - typename pointer_traits::template rebind) + using pointer = __detected_or_t; /** * @brief The allocator's const pointer type. @@ -113,10 +98,9 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(const_pointer, * @c Alloc::const_pointer if that type exists, otherwise * pointer_traits::rebind */ - typedef __const_pointer const_pointer; - -_GLIBCXX_ALLOC_TR_NESTED_TYPE(void_pointer, - typename pointer_traits::template rebind) + using const_pointer + = __detected_or_t<__ptr_rebind, + __c_pointer, _Alloc>; /** * @brief The allocator's void pointer type. @@ -124,10 +108,8 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(void_pointer, * @c Alloc::void_pointer if that type exists, otherwise * pointer_traits::rebind */ - typedef __void_pointer void_pointer; - -_GLIBCXX_ALLOC_TR_NESTED_TYPE(const_void_pointer, - typename pointer_traits::template rebind) + using void_pointer + = __detected_or_t<__ptr_rebind, __v_pointer, _Alloc>; /** * @brief The allocator's const void pointer type. @@ -135,10 +117,9 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(const_void_pointer, * @c Alloc::const_void_pointer if that type exists, otherwise * pointer_traits::rebind */ - typedef __const_void_pointer const_void_pointer; - -_GLIBCXX_ALLOC_TR_NESTED_TYPE(difference_type, - typename pointer_traits::difference_type) + using const_void_pointer + = __detected_or_t<__ptr_rebind, __cv_pointer, + _Alloc>; /** * @brief The allocator's difference type @@ -146,10 +127,9 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(difference_type, * @c Alloc::difference_type if that type exists, otherwise * pointer_traits::difference_type */ - typedef __difference_type difference_type; - -_GLIBCXX_ALLOC_TR_NESTED_TYPE(size_type, - typename make_unsigned::type) + using difference_type + = __detected_or_t::difference_type, + __diff_type, _Alloc>; /** * @brief The allocator's size type @@ -157,10 +137,9 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(size_type, * @c Alloc::size_type if that type exists, otherwise * make_unsigned::type */ - typedef __size_type size_type; - -_GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_copy_assignment, - false_type) + using size_type + = __detected_or_t::type, + __size_type, _Alloc>; /** * @brief How the allocator is propagated on copy assignment @@ -168,11 +147,8 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_copy_assignment, * @c Alloc::propagate_on_container_copy_assignment if that type exists, * otherwise @c false_type */ - typedef __propagate_on_container_copy_assignment - propagate_on_container_copy_assignment; - -_GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_move_assignment, - false_type) + using propagate_on_container_copy_assignment + = __detected_or_t; /** * @brief How the allocator is propagated on move assignment @@ -180,11 +156,8 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_move_assignment, * @c Alloc::propagate_on_container_move_assignment if that type exists, * otherwise @c false_type */ - typedef __propagate_on_container_move_assignment - propagate_on_container_move_assignment; - -_GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap, - false_type) + using propagate_on_container_move_assignment + = __detected_or_t; /** * @brief How the allocator is propagated on swap @@ -192,10 +165,8 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap, * @c Alloc::propagate_on_container_swap if that type exists, * otherwise @c false_type */ - typedef __propagate_on_container_swap propagate_on_container_swap; - -_GLIBCXX_ALLOC_TR_NESTED_TYPE(is_always_equal, - typename is_empty<_Alloc>::type) + using propagate_on_container_swap + = __detected_or_t; /** * @brief Whether all instances of the allocator type compare equal. @@ -203,44 +174,27 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(is_always_equal, * @c Alloc::is_always_equal if that type exists, * otherwise @c is_empty::type */ - typedef __is_always_equal is_always_equal; - -#undef _GLIBCXX_ALLOC_TR_NESTED_TYPE + using is_always_equal + = __detected_or_t::type, __equal, _Alloc>; template - using rebind_alloc = typename __alloctr_rebind<_Alloc, _Tp>::__type; + using rebind_alloc = __alloc_rebind<_Alloc, _Tp>; template using rebind_traits = allocator_traits>; + static_assert(!is_same, __undefined>::value, + "allocator defines rebind or is like Alloc"); + private: template - struct __allocate_helper - { - template()->allocate( - std::declval(), - std::declval()))> - static true_type __test(int); - - template - static false_type __test(...); - - using type = decltype(__test<_Alloc>(0)); - }; - - template - using __has_allocate = typename __allocate_helper<_Alloc2>::type; - - template>> - static pointer - _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint) + static auto + _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint, int) + -> decltype(__a.allocate(__n, __hint)) { return __a.allocate(__n, __hint); } - template>>> + template static pointer - _S_allocate(_Alloc2& __a, size_type __n, _UnusedHint) + _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer, ...) { return __a.allocate(__n); } template @@ -273,57 +227,24 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(is_always_equal, _S_construct(_Alloc&, _Tp* __p, _Args&&... __args) { ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); } - template - struct __destroy_helper - { - template()->destroy( - std::declval<_Tp*>()))> - static true_type __test(int); - - template - static false_type __test(...); - - using type = decltype(__test<_Alloc>(0)); - }; - - template - using __has_destroy = typename __destroy_helper<_Tp>::type; - - template - static _Require<__has_destroy<_Tp>> - _S_destroy(_Alloc& __a, _Tp* __p) + template + static auto + _S_destroy(_Alloc2& __a, _Tp* __p, int) + -> decltype(__a.destroy(__p)) { __a.destroy(__p); } - template - static _Require<__not_<__has_destroy<_Tp>>> - _S_destroy(_Alloc&, _Tp* __p) + template + static void + _S_destroy(_Alloc2&, _Tp* __p, ...) { __p->~_Tp(); } template - struct __maxsize_helper - { - template()->max_size())> - static true_type __test(int); - - template - static false_type __test(...); - - using type = decltype(__test<_Alloc2>(0)); - }; - - template - using __has_max_size = typename __maxsize_helper<_Alloc2>::type; - - template>> - static size_type + static auto _S_max_size(_Alloc2& __a, int) + -> decltype(__a.max_size()) { return __a.max_size(); } - template>>> + template static size_type _S_max_size(_Alloc2&, ...) { @@ -334,30 +255,12 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(is_always_equal, } template - struct __select_helper - { - template() - ->select_on_container_copy_construction())> - static true_type __test(int); - - template - static false_type __test(...); - - using type = decltype(__test<_Alloc2>(0)); - }; - - template - using __has_soccc = typename __select_helper<_Alloc2>::type; - - template>> - static _Alloc2 + static auto _S_select(_Alloc2& __a, int) + -> decltype(__a.select_on_container_copy_construction()) { return __a.select_on_container_copy_construction(); } - template>>> + template static _Alloc2 _S_select(_Alloc2& __a, ...) { return __a; } @@ -388,7 +291,7 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(is_always_equal, */ static pointer allocate(_Alloc& __a, size_type __n, const_void_pointer __hint) - { return _S_allocate(__a, __n, __hint); } + { return _S_allocate(__a, __n, __hint, 0); } /** * @brief Deallocate memory. @@ -398,7 +301,8 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(is_always_equal, * * Calls a.deallocate(p, n) */ - static void deallocate(_Alloc& __a, pointer __p, size_type __n) + static void + deallocate(_Alloc& __a, pointer __p, size_type __n) { __a.deallocate(__p, __n); } /** @@ -427,7 +331,7 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(is_always_equal, */ template static void destroy(_Alloc& __a, _Tp* __p) - { _S_destroy(__a, __p); } + { _S_destroy(__a, __p, 0); } /** * @brief The maximum supported allocation size diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h index 31d237e7783..48810044079 100644 --- a/libstdc++-v3/include/bits/hashtable.h +++ b/libstdc++-v3/include/bits/hashtable.h @@ -179,15 +179,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION public __detail::_Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>, private __detail::_Hashtable_alloc< - typename __alloctr_rebind<_Alloc, - __detail::_Hash_node<_Value, - _Traits::__hash_cached::value> >::__type> + __alloc_rebind<_Alloc, + __detail::_Hash_node<_Value, + _Traits::__hash_cached::value>>> { using __traits_type = _Traits; using __hash_cached = typename __traits_type::__hash_cached; using __node_type = __detail::_Hash_node<_Value, __hash_cached::value>; - using __node_alloc_type = - typename __alloctr_rebind<_Alloc, __node_type>::__type; + using __node_alloc_type = __alloc_rebind<_Alloc, __node_type>; using __hashtable_alloc = __detail::_Hashtable_alloc<__node_alloc_type>; diff --git a/libstdc++-v3/testsuite/20_util/scoped_allocator/propagation.cc b/libstdc++-v3/testsuite/20_util/scoped_allocator/propagation.cc index e1e59460288..a3da6c0a3df 100644 --- a/libstdc++-v3/testsuite/20_util/scoped_allocator/propagation.cc +++ b/libstdc++-v3/testsuite/20_util/scoped_allocator/propagation.cc @@ -41,6 +41,10 @@ template template struct test_allocator : minimal_allocator { + template + struct rebind + { using other = test_allocator; }; + struct propagate_on_container_copy_assignment : std::integral_constant { }; diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/instantiation_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/instantiation_neg.cc index 61848de137e..ac199004b32 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_set/instantiation_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_set/instantiation_neg.cc @@ -19,7 +19,7 @@ // with this library; see the file COPYING3. If not see // . -// { dg-error "with noexcept" "" { target *-*-* } 266 } +// { dg-error "with noexcept" "" { target *-*-* } 265 } #include