commit ea134c1ada93bbeca9f09a06513704639a752d39
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Mon Jun 29 17:08:12 2015 +0100
* include/bits/uses_allocator.h (__uses_alloc_t, __use_alloc): Add
comments.
(__is_allocator): New trait.
(__alloc_arg_t): New SFINAE helper for detecting allocators.
* include/std/tuple (tuple): Replace allocator_arg_t with
__alloc_arg_t<_Alloc>.
* testsuite/20_util/tuple/cons/allocators.cc: Use a valid Allocator.
* testsuite/20_util/uses_allocator/cons_neg.cc: Likewise.
* testsuite/20_util/uses_allocator/construction.cc: Likewise.
@@ -38,6 +38,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// [allocator.tag]
struct allocator_arg_t { };
+ /// A tag of type allocator_arg_t.
constexpr allocator_arg_t allocator_arg = allocator_arg_t();
template<typename _Tp, typename _Alloc, typename = __void_t<>>
@@ -58,14 +59,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __uses_alloc_base { };
+ /// A tag type indicating construction without an allocator.
struct __uses_alloc0 : __uses_alloc_base
{
struct _Sink { void operator=(const void*) { } } _M_a;
};
+ /// A tag type indicating construction with allocator_arg_t.
template<typename _Alloc>
struct __uses_alloc1 : __uses_alloc_base { const _Alloc* _M_a; };
+ /// A tag type indicating construction with an allocator argument at the end.
template<typename _Alloc>
struct __uses_alloc2 : __uses_alloc_base { const _Alloc* _M_a; };
@@ -84,10 +88,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __uses_alloc<false, _Tp, _Alloc, _Args...>
: __uses_alloc0 { };
+ /// A tag type indicating whether/how to construct with an allocator.
template<typename _Tp, typename _Alloc, typename... _Args>
using __uses_alloc_t =
__uses_alloc<uses_allocator<_Tp, _Alloc>::value, _Tp, _Alloc, _Args...>;
+ /// Make a tag type indicating how to use an allocator for construction.
template<typename _Tp, typename _Alloc, typename... _Args>
inline __uses_alloc_t<_Tp, _Alloc, _Args...>
__use_alloc(const _Alloc& __a)
@@ -97,6 +103,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __ret;
}
+ /// Check for required Allocator functions (only as an unevaluated operand).
+ template<typename _Alloc>
+ auto
+ __can_allocate(_Alloc* __a)
+ -> decltype(__a->deallocate(__a->allocate(1u), 1u));
+
+ /// Primary template handles all cases that don't look like Allocators.
+ template<typename _Alloc, typename = __void_t<>>
+ struct __is_allocator_impl
+ : false_type { };
+
+ /// Specialization recognizes types that define value_type and can allocate.
+ template<typename _Alloc>
+ struct __is_allocator_impl<_Alloc,
+ __void_t<typename _Alloc::value_type,
+ decltype(__can_allocate<_Alloc>(0))>>
+ : true_type { };
+
+ /// Detect whether a type might be an Allocator.
+ template<typename _Alloc>
+ struct __is_allocator : __is_allocator_impl<_Alloc>::type
+ { };
+
+ /// Alias for allocator_arg_t that is only valid if _Alloc is an Allocator.
+ template<typename _Alloc>
+ using __alloc_arg_t = typename enable_if<__is_allocator<_Alloc>::value,
+ allocator_arg_t>::type;
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
@@ -640,7 +640,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Allocator-extended constructors.
template<typename _Alloc>
- tuple(allocator_arg_t __tag, const _Alloc& __a)
+ tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a)
: _Inherited(__tag, __a) { }
template<typename _Alloc, typename _Dummy = void,
@@ -650,7 +650,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& _TCC<_Dummy>::template
_ImplicitlyConvertibleTuple<_Elements...>(),
bool>::type=true>
- tuple(allocator_arg_t __tag, const _Alloc& __a,
+ tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a,
const _Elements&... __elements)
: _Inherited(__tag, __a, __elements...) { }
@@ -661,7 +661,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& !_TCC<_Dummy>::template
_ImplicitlyConvertibleTuple<_Elements...>(),
bool>::type=false>
- explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ explicit tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a,
const _Elements&... __elements)
: _Inherited(__tag, __a, __elements...) { }
@@ -671,7 +671,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& _TMC<_UElements...>::template
_ImplicitlyMoveConvertibleTuple<_UElements...>(),
bool>::type=true>
- tuple(allocator_arg_t __tag, const _Alloc& __a,
+ tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a,
_UElements&&... __elements)
: _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
{ }
@@ -682,17 +682,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& !_TMC<_UElements...>::template
_ImplicitlyMoveConvertibleTuple<_UElements...>(),
bool>::type=false>
- explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ explicit tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a,
_UElements&&... __elements)
: _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
{ }
template<typename _Alloc>
- tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
+ tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a, const tuple& __in)
: _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
template<typename _Alloc>
- tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
+ tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a, tuple&& __in)
: _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
template<typename _Alloc, typename... _UElements, typename
@@ -701,7 +701,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& _TMC<_UElements...>::template
_ImplicitlyConvertibleTuple<_UElements...>(),
bool>::type=true>
- tuple(allocator_arg_t __tag, const _Alloc& __a,
+ tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a,
const tuple<_UElements...>& __in)
: _Inherited(__tag, __a,
static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
@@ -713,7 +713,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& !_TMC<_UElements...>::template
_ImplicitlyConvertibleTuple<_UElements...>(),
bool>::type=false>
- explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ explicit tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a,
const tuple<_UElements...>& __in)
: _Inherited(__tag, __a,
static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
@@ -725,7 +725,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& _TMC<_UElements...>::template
_ImplicitlyMoveConvertibleTuple<_UElements...>(),
bool>::type=true>
- tuple(allocator_arg_t __tag, const _Alloc& __a,
+ tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a,
tuple<_UElements...>&& __in)
: _Inherited(__tag, __a,
static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
@@ -737,7 +737,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& !_TMC<_UElements...>::template
_ImplicitlyMoveConvertibleTuple<_UElements...>(),
bool>::type=false>
- explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ explicit tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a,
tuple<_UElements...>&& __in)
: _Inherited(__tag, __a,
static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
@@ -936,7 +936,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Allocator-extended constructors.
template<typename _Alloc>
- tuple(allocator_arg_t __tag, const _Alloc& __a)
+ tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a)
: _Inherited(__tag, __a) { }
template<typename _Alloc, typename _Dummy = void,
@@ -947,7 +947,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_ImplicitlyConvertibleTuple<_T1, _T2>(),
bool>::type=true>
- tuple(allocator_arg_t __tag, const _Alloc& __a,
+ tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a,
const _T1& __a1, const _T2& __a2)
: _Inherited(__tag, __a, __a1, __a2) { }
@@ -959,7 +959,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_ImplicitlyConvertibleTuple<_T1, _T2>(),
bool>::type=false>
- explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ explicit tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a,
const _T1& __a1, const _T2& __a2)
: _Inherited(__tag, __a, __a1, __a2) { }
@@ -969,7 +969,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& _TMC::template
_ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
bool>::type = true>
- tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
+ tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a, _U1&& __a1,
+ _U2&& __a2)
: _Inherited(__tag, __a, std::forward<_U1>(__a1),
std::forward<_U2>(__a2)) { }
@@ -979,17 +980,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& !_TMC::template
_ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
bool>::type = false>
- explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ explicit tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a,
_U1&& __a1, _U2&& __a2)
: _Inherited(__tag, __a, std::forward<_U1>(__a1),
std::forward<_U2>(__a2)) { }
template<typename _Alloc>
- tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
+ tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a, const tuple& __in)
: _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
template<typename _Alloc>
- tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
+ tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a, tuple&& __in)
: _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
template<typename _Alloc, typename _U1, typename _U2, typename
@@ -998,7 +999,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& _TMC::template
_ImplicitlyConvertibleTuple<_U1, _U2>(),
bool>::type = true>
- tuple(allocator_arg_t __tag, const _Alloc& __a,
+ tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a,
const tuple<_U1, _U2>& __in)
: _Inherited(__tag, __a,
static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
@@ -1010,7 +1011,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& !_TMC::template
_ImplicitlyConvertibleTuple<_U1, _U2>(),
bool>::type = false>
- explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ explicit tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a,
const tuple<_U1, _U2>& __in)
: _Inherited(__tag, __a,
static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
@@ -1022,7 +1023,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& _TMC::template
_ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
bool>::type = true>
- tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
+ tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
: _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
{ }
@@ -1032,7 +1033,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& !_TMC::template
_ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
bool>::type = false>
- explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ explicit tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a,
tuple<_U1, _U2>&& __in)
: _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
{ }
@@ -1043,7 +1044,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& _TMC::template
_ImplicitlyConvertibleTuple<_U1, _U2>(),
bool>::type = true>
- tuple(allocator_arg_t __tag, const _Alloc& __a,
+ tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a,
const pair<_U1, _U2>& __in)
: _Inherited(__tag, __a, __in.first, __in.second) { }
@@ -1053,7 +1054,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& !_TMC::template
_ImplicitlyConvertibleTuple<_U1, _U2>(),
bool>::type = false>
- explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ explicit tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a,
const pair<_U1, _U2>& __in)
: _Inherited(__tag, __a, __in.first, __in.second) { }
@@ -1063,7 +1064,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& _TMC::template
_ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
bool>::type = true>
- tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
+ tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a,
+ pair<_U1, _U2>&& __in)
: _Inherited(__tag, __a, std::forward<_U1>(__in.first),
std::forward<_U2>(__in.second)) { }
@@ -1073,7 +1075,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& !_TMC::template
_ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
bool>::type = false>
- explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ explicit tuple(__alloc_arg_t<_Alloc> __tag, const _Alloc& __a,
pair<_U1, _U2>&& __in)
: _Inherited(__tag, __a, std::forward<_U1>(__in.first),
std::forward<_U2>(__in.second)) { }
@@ -22,8 +22,9 @@
#include <memory>
#include <tuple>
#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
-struct MyAlloc { };
+using MyAlloc = __gnu_test::SimpleAllocator<int>;
// type that can't be constructed with an allocator
struct CannotUse
@@ -22,8 +22,9 @@
#include <memory>
#include <tuple>
+#include <testsuite_allocator.h>
-struct MyAlloc { };
+using MyAlloc = __gnu_test::SimpleAllocator<int>;
struct Type
{
@@ -22,8 +22,9 @@
#include <memory>
#include <tuple>
#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
-struct MyAlloc { };
+using MyAlloc = __gnu_test::SimpleAllocator<int>;
// type that can't be constructed with an allocator
struct CannotUse