alloc_traits.h (__alloctr_rebind): Remove.
* 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. From-SVN: r225244
This commit is contained in:
parent
4f44c5556f
commit
7946683835
@ -1,5 +1,17 @@
|
||||
2015-07-01 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
* 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
|
||||
|
@ -40,72 +40,57 @@ namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
template<typename _Alloc, typename _Tp>
|
||||
class __alloctr_rebind_helper
|
||||
{
|
||||
template<typename _Alloc2, typename _Tp2>
|
||||
static constexpr true_type
|
||||
_S_chk(typename _Alloc2::template rebind<_Tp2>::other*);
|
||||
struct __allocator_traits_base
|
||||
{
|
||||
template<typename _Alloc, typename _Up>
|
||||
using __rebind = typename _Alloc::template rebind<_Up>::other;
|
||||
|
||||
template<typename, typename>
|
||||
static constexpr false_type
|
||||
_S_chk(...);
|
||||
protected:
|
||||
template<typename _Tp>
|
||||
using __pointer = typename _Tp::pointer;
|
||||
template<typename _Tp>
|
||||
using __c_pointer = typename _Tp::const_pointer;
|
||||
template<typename _Tp>
|
||||
using __v_pointer = typename _Tp::void_pointer;
|
||||
template<typename _Tp>
|
||||
using __cv_pointer = typename _Tp::const_void_pointer;
|
||||
template<typename _Tp>
|
||||
using __diff_type = typename _Tp::difference_type;
|
||||
template<typename _Tp>
|
||||
using __size_type = typename _Tp::size_type;
|
||||
template<typename _Tp>
|
||||
using __pocca = typename _Tp::propagate_on_container_copy_assignment;
|
||||
template<typename _Tp>
|
||||
using __pocma = typename _Tp::propagate_on_container_move_assignment;
|
||||
template<typename _Tp>
|
||||
using __pocs = typename _Tp::propagate_on_container_swap;
|
||||
template<typename _Tp>
|
||||
using __equal = typename _Tp::is_always_equal;
|
||||
};
|
||||
|
||||
public:
|
||||
using __type = decltype(_S_chk<_Alloc, _Tp>(nullptr));
|
||||
};
|
||||
|
||||
template<typename _Alloc, typename _Tp,
|
||||
bool = __alloctr_rebind_helper<_Alloc, _Tp>::__type::value>
|
||||
struct __alloctr_rebind;
|
||||
|
||||
template<typename _Alloc, typename _Tp>
|
||||
struct __alloctr_rebind<_Alloc, _Tp, true>
|
||||
{
|
||||
typedef typename _Alloc::template rebind<_Tp>::other __type;
|
||||
};
|
||||
|
||||
template<template<typename, typename...> class _Alloc, typename _Tp,
|
||||
typename _Up, typename... _Args>
|
||||
struct __alloctr_rebind<_Alloc<_Up, _Args...>, _Tp, false>
|
||||
{
|
||||
typedef _Alloc<_Tp, _Args...> __type;
|
||||
};
|
||||
|
||||
template<typename _Alloc, typename _Tp>
|
||||
using __alloc_rebind = typename __alloctr_rebind<_Alloc, _Tp>::__type;
|
||||
template<typename _Alloc, typename _Up>
|
||||
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<typename _Alloc>
|
||||
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<typename _Tp> \
|
||||
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<pointer>::template rebind<const value_type>)
|
||||
using pointer = __detected_or_t<value_type*, __pointer, _Alloc>;
|
||||
|
||||
/**
|
||||
* @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
|
||||
* <tt> pointer_traits<pointer>::rebind<const value_type> </tt>
|
||||
*/
|
||||
typedef __const_pointer const_pointer;
|
||||
|
||||
_GLIBCXX_ALLOC_TR_NESTED_TYPE(void_pointer,
|
||||
typename pointer_traits<pointer>::template rebind<void>)
|
||||
using const_pointer
|
||||
= __detected_or_t<__ptr_rebind<pointer, const value_type>,
|
||||
__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
|
||||
* <tt> pointer_traits<pointer>::rebind<void> </tt>
|
||||
*/
|
||||
typedef __void_pointer void_pointer;
|
||||
|
||||
_GLIBCXX_ALLOC_TR_NESTED_TYPE(const_void_pointer,
|
||||
typename pointer_traits<pointer>::template rebind<const void>)
|
||||
using void_pointer
|
||||
= __detected_or_t<__ptr_rebind<pointer, void>, __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
|
||||
* <tt> pointer_traits<pointer>::rebind<const void> </tt>
|
||||
*/
|
||||
typedef __const_void_pointer const_void_pointer;
|
||||
|
||||
_GLIBCXX_ALLOC_TR_NESTED_TYPE(difference_type,
|
||||
typename pointer_traits<pointer>::difference_type)
|
||||
using const_void_pointer
|
||||
= __detected_or_t<__ptr_rebind<pointer, const void>, __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
|
||||
* <tt> pointer_traits<pointer>::difference_type </tt>
|
||||
*/
|
||||
typedef __difference_type difference_type;
|
||||
|
||||
_GLIBCXX_ALLOC_TR_NESTED_TYPE(size_type,
|
||||
typename make_unsigned<difference_type>::type)
|
||||
using difference_type
|
||||
= __detected_or_t<typename pointer_traits<pointer>::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
|
||||
* <tt> make_unsigned<difference_type>::type </tt>
|
||||
*/
|
||||
typedef __size_type size_type;
|
||||
|
||||
_GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_copy_assignment,
|
||||
false_type)
|
||||
using size_type
|
||||
= __detected_or_t<typename make_unsigned<difference_type>::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<false_type, __pocca, _Alloc>;
|
||||
|
||||
/**
|
||||
* @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<false_type, __pocma, _Alloc>;
|
||||
|
||||
/**
|
||||
* @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<false_type, __pocs, _Alloc>;
|
||||
|
||||
/**
|
||||
* @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<Alloc>::type
|
||||
*/
|
||||
typedef __is_always_equal is_always_equal;
|
||||
|
||||
#undef _GLIBCXX_ALLOC_TR_NESTED_TYPE
|
||||
using is_always_equal
|
||||
= __detected_or_t<typename is_empty<_Alloc>::type, __equal, _Alloc>;
|
||||
|
||||
template<typename _Tp>
|
||||
using rebind_alloc = typename __alloctr_rebind<_Alloc, _Tp>::__type;
|
||||
using rebind_alloc = __alloc_rebind<_Alloc, _Tp>;
|
||||
template<typename _Tp>
|
||||
using rebind_traits = allocator_traits<rebind_alloc<_Tp>>;
|
||||
|
||||
static_assert(!is_same<rebind_alloc<value_type>, __undefined>::value,
|
||||
"allocator defines rebind or is like Alloc<T, Args>");
|
||||
|
||||
private:
|
||||
template<typename _Alloc2>
|
||||
struct __allocate_helper
|
||||
{
|
||||
template<typename _Alloc3,
|
||||
typename = decltype(std::declval<_Alloc3*>()->allocate(
|
||||
std::declval<size_type>(),
|
||||
std::declval<const_void_pointer>()))>
|
||||
static true_type __test(int);
|
||||
|
||||
template<typename>
|
||||
static false_type __test(...);
|
||||
|
||||
using type = decltype(__test<_Alloc>(0));
|
||||
};
|
||||
|
||||
template<typename _Alloc2>
|
||||
using __has_allocate = typename __allocate_helper<_Alloc2>::type;
|
||||
|
||||
template<typename _Alloc2,
|
||||
typename = _Require<__has_allocate<_Alloc2>>>
|
||||
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<typename _Alloc2, typename _UnusedHint,
|
||||
typename = _Require<__not_<__has_allocate<_Alloc2>>>>
|
||||
template<typename _Alloc2>
|
||||
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<typename _Tp, typename... _Args>
|
||||
@ -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<typename _Tp>
|
||||
struct __destroy_helper
|
||||
{
|
||||
template<typename _Alloc2,
|
||||
typename = decltype(std::declval<_Alloc2*>()->destroy(
|
||||
std::declval<_Tp*>()))>
|
||||
static true_type __test(int);
|
||||
|
||||
template<typename>
|
||||
static false_type __test(...);
|
||||
|
||||
using type = decltype(__test<_Alloc>(0));
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
using __has_destroy = typename __destroy_helper<_Tp>::type;
|
||||
|
||||
template<typename _Tp>
|
||||
static _Require<__has_destroy<_Tp>>
|
||||
_S_destroy(_Alloc& __a, _Tp* __p)
|
||||
template<typename _Alloc2, typename _Tp>
|
||||
static auto
|
||||
_S_destroy(_Alloc2& __a, _Tp* __p, int)
|
||||
-> decltype(__a.destroy(__p))
|
||||
{ __a.destroy(__p); }
|
||||
|
||||
template<typename _Tp>
|
||||
static _Require<__not_<__has_destroy<_Tp>>>
|
||||
_S_destroy(_Alloc&, _Tp* __p)
|
||||
template<typename _Alloc2, typename _Tp>
|
||||
static void
|
||||
_S_destroy(_Alloc2&, _Tp* __p, ...)
|
||||
{ __p->~_Tp(); }
|
||||
|
||||
template<typename _Alloc2>
|
||||
struct __maxsize_helper
|
||||
{
|
||||
template<typename _Alloc3,
|
||||
typename = decltype(std::declval<_Alloc3*>()->max_size())>
|
||||
static true_type __test(int);
|
||||
|
||||
template<typename>
|
||||
static false_type __test(...);
|
||||
|
||||
using type = decltype(__test<_Alloc2>(0));
|
||||
};
|
||||
|
||||
template<typename _Alloc2>
|
||||
using __has_max_size = typename __maxsize_helper<_Alloc2>::type;
|
||||
|
||||
template<typename _Alloc2,
|
||||
typename = _Require<__has_max_size<_Alloc2>>>
|
||||
static size_type
|
||||
static auto
|
||||
_S_max_size(_Alloc2& __a, int)
|
||||
-> decltype(__a.max_size())
|
||||
{ return __a.max_size(); }
|
||||
|
||||
template<typename _Alloc2,
|
||||
typename = _Require<__not_<__has_max_size<_Alloc2>>>>
|
||||
template<typename _Alloc2>
|
||||
static size_type
|
||||
_S_max_size(_Alloc2&, ...)
|
||||
{
|
||||
@ -334,30 +255,12 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(is_always_equal,
|
||||
}
|
||||
|
||||
template<typename _Alloc2>
|
||||
struct __select_helper
|
||||
{
|
||||
template<typename _Alloc3, typename
|
||||
= decltype(std::declval<_Alloc3*>()
|
||||
->select_on_container_copy_construction())>
|
||||
static true_type __test(int);
|
||||
|
||||
template<typename>
|
||||
static false_type __test(...);
|
||||
|
||||
using type = decltype(__test<_Alloc2>(0));
|
||||
};
|
||||
|
||||
template<typename _Alloc2>
|
||||
using __has_soccc = typename __select_helper<_Alloc2>::type;
|
||||
|
||||
template<typename _Alloc2,
|
||||
typename = _Require<__has_soccc<_Alloc2>>>
|
||||
static _Alloc2
|
||||
static auto
|
||||
_S_select(_Alloc2& __a, int)
|
||||
-> decltype(__a.select_on_container_copy_construction())
|
||||
{ return __a.select_on_container_copy_construction(); }
|
||||
|
||||
template<typename _Alloc2,
|
||||
typename = _Require<__not_<__has_soccc<_Alloc2>>>>
|
||||
template<typename _Alloc2>
|
||||
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 <tt> a.deallocate(p, n) </tt>
|
||||
*/
|
||||
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 <class _Tp>
|
||||
static void destroy(_Alloc& __a, _Tp* __p)
|
||||
{ _S_destroy(__a, __p); }
|
||||
{ _S_destroy(__a, __p, 0); }
|
||||
|
||||
/**
|
||||
* @brief The maximum supported allocation size
|
||||
|
@ -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>;
|
||||
|
||||
|
@ -41,6 +41,10 @@ template<typename T>
|
||||
template<typename T, bool copy, bool move, bool swap>
|
||||
struct test_allocator : minimal_allocator<T>
|
||||
{
|
||||
template<typename U>
|
||||
struct rebind
|
||||
{ using other = test_allocator<U, copy, move, swap>; };
|
||||
|
||||
struct propagate_on_container_copy_assignment
|
||||
: std::integral_constant<bool, copy> { };
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-error "with noexcept" "" { target *-*-* } 266 }
|
||||
// { dg-error "with noexcept" "" { target *-*-* } 265 }
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user