tuple: Implement uses-allocator construction.
authorJonathan Wakely <jwakely.gcc@gmail.com>
Mon, 30 May 2011 16:31:17 +0000 (16:31 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Mon, 30 May 2011 16:31:17 +0000 (17:31 +0100)
2011-05-30  Jonathan Wakely  <jwakely.gcc@gmail.com>

* include/std/tuple: Implement uses-allocator construction.
* include/bits/allocator.h (uses_allocator): Move to ...
* include/bits/uses_allocator.h: New file.
* include/Makefile.am: Add new header.
* include/Makefile.in: Regenerate.
* testsuite/20_util/uses_allocator/cons_neg.cc: New.
* testsuite/20_util/uses_allocator/construction.cc: New.
* testsuite/20_util/tuple/cons/allocate_noncopyable.cc: New.
* testsuite/20_util/tuple/cons/allocators.cc: New.

From-SVN: r174443

libstdc++-v3/ChangeLog
libstdc++-v3/include/Makefile.am
libstdc++-v3/include/Makefile.in
libstdc++-v3/include/bits/allocator.h
libstdc++-v3/include/bits/uses_allocator.h [new file with mode: 0644]
libstdc++-v3/include/std/tuple
libstdc++-v3/testsuite/20_util/tuple/cons/allocate_noncopyable.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/tuple/cons/allocators.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/uses_allocator/construction.cc [new file with mode: 0644]

index 1ddef589fa9fcbbbb15d0e2a3a23bd9a8484bceb..9875d6c6f426b545b6fabfb917771ebae0036032 100644 (file)
@@ -1,3 +1,15 @@
+2011-05-30  Jonathan Wakely  <jwakely.gcc@gmail.com>
+
+       * include/std/tuple: Implement uses-allocator construction.
+       * include/bits/allocator.h (uses_allocator): Move to ...
+       * include/bits/uses_allocator.h: New file.
+       * include/Makefile.am: Add new header.
+       * include/Makefile.in: Regenerate.
+       * testsuite/20_util/uses_allocator/cons_neg.cc: New.
+       * testsuite/20_util/uses_allocator/construction.cc: New.
+       * testsuite/20_util/tuple/cons/allocate_noncopyable.cc: New.
+       * testsuite/20_util/tuple/cons/allocators.cc: New.
+
 2011-05-28  Jonathan Wakely  <jwakely.gcc@gmail.com>
 
        * testsuite/20_util/pointer_traits/pointer_to.cc: Fix.
index d83678347d9676323abd1b6aa0dfd76601247144..a4b7f27aaa4fff8da7b372d2248b01604869e1a3 100644 (file)
@@ -168,6 +168,7 @@ bits_headers = \
        ${bits_srcdir}/unique_ptr.h \
        ${bits_srcdir}/unordered_map.h \
        ${bits_srcdir}/unordered_set.h \
+       ${bits_srcdir}/uses_allocator.h \
        ${bits_srcdir}/valarray_array.h \
        ${bits_srcdir}/valarray_array.tcc \
        ${bits_srcdir}/valarray_before.h \
index fedba33196da235c7b0a3f89203e7ccb128bfb94..3cbe0e4500ece415be8f9af56ef26dd45cc24050 100644 (file)
@@ -419,6 +419,7 @@ bits_headers = \
        ${bits_srcdir}/unique_ptr.h \
        ${bits_srcdir}/unordered_map.h \
        ${bits_srcdir}/unordered_set.h \
+       ${bits_srcdir}/uses_allocator.h \
        ${bits_srcdir}/valarray_array.h \
        ${bits_srcdir}/valarray_array.tcc \
        ${bits_srcdir}/valarray_before.h \
index 37c6a596b9189c07cf10b22bf814ee0123c61e76..6fccba51bb1ec8e7ed7784c3c9a0ac7049787982 100644 (file)
@@ -49,7 +49,7 @@
 
 #ifdef __GXX_EXPERIMENTAL_CXX0X__
 #include <bits/ptr_traits.h>
-#include <type_traits> // For _GLIBCXX_HAS_NESTED_TYPE
+#include <bits/uses_allocator.h>
 #include <limits>
 #endif
 
@@ -207,32 +207,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       }
     };
 
-
-  /// [allocator.tag]
-  struct allocator_arg_t { };
-
-  constexpr allocator_arg_t allocator_arg = allocator_arg_t();
-
-_GLIBCXX_HAS_NESTED_TYPE(allocator_type)
-
-  template<typename _Tp, typename _Alloc,
-          bool = __has_allocator_type<_Tp>::value>
-    struct __uses_allocator_helper
-    : public false_type { };
-
-  template<typename _Tp, typename _Alloc>
-    struct __uses_allocator_helper<_Tp, _Alloc, true>
-    : public integral_constant<bool, is_convertible<_Alloc,
-                                    typename _Tp::allocator_type>::value>
-    { };
-
-  /// [allocator.uses.trait]
-  template<typename _Tp, typename _Alloc>
-    struct uses_allocator
-    : public integral_constant<bool,
-                              __uses_allocator_helper<_Tp, _Alloc>::value>
-    { };
-
   template<typename _Alloc, typename _Tp>
     class __alloctr_rebind_helper
     {
diff --git a/libstdc++-v3/include/bits/uses_allocator.h b/libstdc++-v3/include/bits/uses_allocator.h
new file mode 100644 (file)
index 0000000..49b5409
--- /dev/null
@@ -0,0 +1,109 @@
+// Uses-allocator Construction -*- C++ -*-
+
+// Copyright (C) 2010, 2011 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef _USES_ALLOCATOR_H
+#define _USES_ALLOCATOR_H 1
+
+#ifndef __GXX_EXPERIMENTAL_CXX0X__
+# include <bits/c++0x_warning.h>
+#else
+
+#include <type_traits>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  /// [allocator.tag]
+  struct allocator_arg_t { };
+
+  constexpr allocator_arg_t allocator_arg = allocator_arg_t();
+
+_GLIBCXX_HAS_NESTED_TYPE(allocator_type)
+
+  template<typename _Tp, typename _Alloc,
+          bool = __has_allocator_type<_Tp>::value>
+    struct __uses_allocator_helper
+    : public false_type { };
+
+  template<typename _Tp, typename _Alloc>
+    struct __uses_allocator_helper<_Tp, _Alloc, true>
+    : public integral_constant<bool, is_convertible<_Alloc,
+                                    typename _Tp::allocator_type>::value>
+    { };
+
+  /// [allocator.uses.trait]
+  template<typename _Tp, typename _Alloc>
+    struct uses_allocator
+    : public integral_constant<bool,
+                              __uses_allocator_helper<_Tp, _Alloc>::value>
+    { };
+
+  template<typename _Tp, typename _Alloc, typename... _Args>
+    struct __uses_allocator_arg
+    : is_constructible<_Tp, _Alloc, _Args...>
+    { static_assert( uses_allocator<_Tp, _Alloc>::value, "uses allocator" ); };
+
+  struct __uses_alloc_base { };
+  struct __uses_alloc0 : __uses_alloc_base
+  { struct _Anything { _Anything(...) { } } _M_a; };
+  template<typename _Alloc>
+    struct __uses_alloc1 : __uses_alloc_base { const _Alloc* _M_a; };
+  template<typename _Alloc>
+    struct __uses_alloc2 : __uses_alloc_base { const _Alloc* _M_a; };
+
+  template<bool, typename _Alloc, typename... _Args>
+    struct __uses_alloc;
+
+  template<typename _Tp, typename _Alloc, typename... _Args>
+    struct __uses_alloc<true, _Tp, _Alloc, _Args...>
+    : conditional<
+        is_constructible<_Tp, allocator_arg_t, _Alloc, _Args...>::value,
+        __uses_alloc1<_Alloc>,
+               __uses_alloc2<_Alloc>>::type
+    { };
+
+  template<typename _Tp, typename _Alloc, typename... _Args>
+    struct __uses_alloc<false, _Tp, _Alloc, _Args...>
+    : __uses_alloc0 { };
+
+  template<typename _Tp, typename _Alloc, typename... _Args>
+    struct __uses_alloc_impl
+    : __uses_alloc<uses_allocator<_Tp, _Alloc>::value, _Tp,  _Alloc, _Args...>
+    { };
+
+  template<typename _Tp, typename _Alloc, typename... _Args>
+    __uses_alloc_impl<_Tp, _Alloc, _Args...>
+    __use_alloc(const _Alloc& __a)
+    {
+      __uses_alloc_impl<_Tp, _Alloc, _Args...> __ret;
+      __ret._M_a = &__a;
+      return __ret;
+    }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#endif
+#endif
index fee94e26e52cf83e80e38da652ef3f57216fda18..a0e9e694dc2bb586dfffecd5aee68373b75e88c2 100644 (file)
@@ -36,6 +36,7 @@
 #else
 
 #include <utility>
+#include <bits/uses_allocator.h>
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
@@ -81,10 +82,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       constexpr _Head_base(const _Head& __h)
       : _Head(__h) { }
 
-      template<typename _UHead>
+      template<typename _UHead, typename = typename
+              enable_if<!is_convertible<_UHead,
+                                        __uses_alloc_base>::value>::type>
         _Head_base(_UHead&& __h)
        : _Head(std::forward<_UHead>(__h)) { }
 
+      _Head_base(__uses_alloc0)
+      : _Head() { }
+
+      template<typename _Alloc>
+       _Head_base(__uses_alloc1<_Alloc> __a)
+       : _Head(allocator_arg, *__a._M_a) { }
+
+      template<typename _Alloc>
+       _Head_base(__uses_alloc2<_Alloc> __a)
+       : _Head(*__a._M_a) { }
+
+      template<typename _UHead>
+       _Head_base(__uses_alloc0, _UHead&& __uhead)
+       : _Head(std::forward<_UHead>(__uhead)) { }
+
+      template<typename _Alloc, typename _UHead>
+       _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
+       : _Head(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) { }
+
+      template<typename _Alloc, typename _UHead>
+       _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
+       : _Head(std::forward<_UHead>(__uhead), *__a._M_a) { }
+
       _Head&       _M_head() noexcept       { return *this; }
       const _Head& _M_head() const noexcept { return *this; }
     };
@@ -98,10 +124,36 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       constexpr _Head_base(const _Head& __h)
       : _M_head_impl(__h) { }
 
-      template<typename _UHead>
+      template<typename _UHead, typename = typename
+              enable_if<!is_convertible<_UHead,
+                                        __uses_alloc_base>::value>::type>
         _Head_base(_UHead&& __h)
        : _M_head_impl(std::forward<_UHead>(__h)) { }
 
+      _Head_base(__uses_alloc0)
+      : _M_head_impl() { }
+
+      template<typename _Alloc>
+       _Head_base(__uses_alloc1<_Alloc> __a)
+       : _M_head_impl(allocator_arg, *__a._M_a) { }
+
+      template<typename _Alloc>
+       _Head_base(__uses_alloc2<_Alloc> __a)
+       : _M_head_impl(*__a._M_a) { }
+
+      template<typename _UHead>
+       _Head_base(__uses_alloc0, _UHead&& __uhead)
+       : _M_head_impl(std::forward<_UHead>(__uhead)) { }
+
+      template<typename _Alloc, typename _UHead>
+       _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
+       : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
+       { }
+
+      template<typename _Alloc, typename _UHead>
+       _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
+       : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
+
       _Head&       _M_head() noexcept       { return _M_head_impl; }
       const _Head& _M_head() const noexcept { return _M_head_impl; }        
 
@@ -128,6 +180,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     {
       template<std::size_t, typename...> friend class _Tuple_impl;
 
+      _Tuple_impl() = default;
+
+      template<typename _Alloc>
+        _Tuple_impl(allocator_arg_t, const _Alloc&) { }
+
+      template<typename _Alloc>
+        _Tuple_impl(allocator_arg_t, const _Alloc&, const _Tuple_impl&) { }
+
+      template<typename _Alloc>
+        _Tuple_impl(allocator_arg_t, const _Alloc&, _Tuple_impl&&) { }
+
     protected:
       void _M_swap(_Tuple_impl&) noexcept { /* no-op */ }
     };
@@ -160,7 +223,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       constexpr _Tuple_impl(const _Head& __head, const _Tail&... __tail)
       : _Inherited(__tail...), _Base(__head) { }
 
-      template<typename _UHead, typename... _UTail> 
+      template<typename _UHead, typename... _UTail, typename = typename
+               std::enable_if<sizeof...(_Tail)==sizeof...(_UTail)>::type> 
         explicit
         _Tuple_impl(_UHead&& __head, _UTail&&... __tail)
        : _Inherited(std::forward<_UTail>(__tail)...),
@@ -183,6 +247,54 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        : _Inherited(std::move(__in._M_tail())),
          _Base(std::forward<_UHead>(__in._M_head())) { }
 
+      template<typename _Alloc>
+       _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
+       : _Inherited(__tag, __a),
+          _Base(__use_alloc<_Head>(__a)) { }
+
+      template<typename _Alloc>
+       _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
+           const _Head& __head, const _Tail&... __tail)
+       : _Inherited(__tag, __a, __tail...),
+          _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head) { }
+
+      template<typename _Alloc, typename _UHead, typename... _UTail,
+               typename = typename std::enable_if<sizeof...(_Tail)
+                                                 ==sizeof...(_UTail)>::type>
+       _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
+                   _UHead&& __head, _UTail&&... __tail)
+       : _Inherited(__tag, __a, std::forward<_UTail>(__tail)...),
+          _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
+               std::forward<_UHead>(__head)) { }
+
+      template<typename _Alloc>
+        _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
+                   const _Tuple_impl& __in)
+       : _Inherited(__tag, __a, __in._M_tail()), 
+          _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __in._M_head()) { }
+
+      template<typename _Alloc>
+       _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
+                   _Tuple_impl&& __in)
+       noexcept(std::is_nothrow_move_constructible<_Head>::value
+                && std::is_nothrow_move_constructible<_Inherited>::value)
+       : _Inherited(__tag, __a, std::move(__in._M_tail())), 
+         _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
+               std::forward<_Head>(__in._M_head())) { }
+
+      template<typename _Alloc, typename... _UElements>
+       _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
+                   const _Tuple_impl<_Idx, _UElements...>& __in)
+       : _Inherited(__tag, __a, __in._M_tail()),
+         _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __in._M_head()) { }
+
+      template<typename _Alloc, typename _UHead, typename... _UTails>
+       _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
+                   _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
+       : _Inherited(__tag, __a, std::move(__in._M_tail())),
+         _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
+                std::forward<_UHead>(__in._M_head())) { }
+
       _Tuple_impl&
       operator=(const _Tuple_impl& __in)
       {
@@ -269,6 +381,51 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         tuple(tuple<_UElements...>&& __in)
         : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
 
+      // allocator-extended constructors
+
+      template<typename _Alloc>
+       tuple(allocator_arg_t __tag, const _Alloc& __a)
+       : _Inherited(__tag, __a) { }
+
+      template<typename _Alloc>
+       tuple(allocator_arg_t __tag, const _Alloc& __a,
+             const _Elements&... __elements)
+       : _Inherited(__tag, __a, __elements...) { }
+
+      template<typename _Alloc, typename... _UElements, typename = typename
+              std::enable_if<sizeof...(_UElements)
+                             == sizeof...(_Elements)>::type>
+       tuple(allocator_arg_t __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)
+       : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
+
+      template<typename _Alloc>
+       tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
+       : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
+
+      template<typename _Alloc, typename... _UElements, typename = typename
+              std::enable_if<sizeof...(_UElements)
+                             == sizeof...(_Elements)>::type>
+       tuple(allocator_arg_t __tag, const _Alloc& __a,
+             const tuple<_UElements...>& __in)
+       : _Inherited(__tag, __a,
+                    static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
+       { }
+
+      template<typename _Alloc, typename... _UElements, typename = typename
+              std::enable_if<sizeof...(_UElements)
+                             == sizeof...(_Elements)>::type>
+       tuple(allocator_arg_t __tag, const _Alloc& __a,
+             tuple<_UElements...>&& __in)
+       : _Inherited(__tag, __a,
+                    static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
+       { }
+
       tuple&
       operator=(const tuple& __in)
       {
@@ -356,6 +513,52 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        : _Inherited(std::forward<_U1>(__in.first),
                     std::forward<_U2>(__in.second)) { }
 
+      // allocator-extended constructors
+
+      template<typename _Alloc>
+       tuple(allocator_arg_t __tag, const _Alloc& __a)
+       : _Inherited(__tag, __a) { }
+
+      template<typename _Alloc>
+       tuple(allocator_arg_t __tag, const _Alloc& __a,
+             const _T1& __a1, const _T2& __a2)
+       : _Inherited(__tag, __a, __a1, __a2) { }
+
+      template<typename _Alloc, typename _U1, typename _U2>
+       tuple(allocator_arg_t __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)
+       : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
+
+      template<typename _Alloc>
+       tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
+       : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
+
+      template<typename _Alloc, typename _U1, typename _U2>
+       tuple(allocator_arg_t __tag, const _Alloc& __a,
+             const tuple<_U1, _U2>& __in)
+       : _Inherited(__tag, __a,
+                    static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
+       { }
+
+      template<typename _Alloc, typename _U1, typename _U2>
+       tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
+       : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
+       { }
+
+      template<typename _Alloc, typename _U1, typename _U2>
+        tuple(allocator_arg_t __tag, const _Alloc& __a,
+             const pair<_U1, _U2>& __in)
+       : _Inherited(__tag, __a, __in.first, __in.second) { }
+
+      template<typename _Alloc, typename _U1, typename _U2>
+        tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
+       : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
+                    std::forward<_U2>(__in.second)) { }
+
       tuple&
       operator=(const tuple& __in)
       {
@@ -426,7 +629,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       : _Inherited(__a1) { }
 
       template<typename _U1, typename = typename
-              std::enable_if<std::is_convertible<_U1, _T1>::value>::type>
+              std::enable_if<std::is_constructible<_T1, _U1&&>::value>::type>
         explicit
         tuple(_U1&& __a1)
        : _Inherited(std::forward<_U1>(__a1)) { }
@@ -442,6 +645,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         tuple(tuple<_U1>&& __in)
        : _Inherited(static_cast<_Tuple_impl<0, _U1>&&>(__in)) { }
 
+      // allocator-extended constructors
+
+      template<typename _Alloc>
+       tuple(allocator_arg_t __tag, const _Alloc& __a)
+       : _Inherited(__tag, __a) { }
+
+      template<typename _Alloc>
+       tuple(allocator_arg_t __tag, const _Alloc& __a, const _T1& __a1)
+       : _Inherited(__tag, __a, __a1) { }
+
+      // TODO: constrain for is_uses_allocator_constructible<_T1, _U1&&, _Alloc>
+      template<typename _Alloc, typename _U1>
+       tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1)
+       : _Inherited(__tag, __a, std::forward<_U1>(__a1)) { }
+
+      template<typename _Alloc>
+       tuple(allocator_arg_t __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)
+       : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
+
+      template<typename _Alloc, typename _U1>
+       tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple<_U1>& __in)
+       : _Inherited(__tag, __a, static_cast<const _Tuple_impl<0, _U1>&>(__in))
+               { }
+
+      template<typename _Alloc, typename _U1>
+       tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1>&& __in)
+       : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1>&&>(__in)) { }
+
       tuple&
       operator=(const tuple& __in)
       {
@@ -804,6 +1039,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   const _Swallow_assign ignore{};
 
+  /// Partial specialization for tuples
+  template<typename... _Types, typename _Alloc>
+    struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { };
+
   /**
    * Stores a tuple of indices. Used by bind() to extract the elements
    * in a tuple. 
diff --git a/libstdc++-v3/testsuite/20_util/tuple/cons/allocate_noncopyable.cc b/libstdc++-v3/testsuite/20_util/tuple/cons/allocate_noncopyable.cc
new file mode 100644 (file)
index 0000000..d729178
--- /dev/null
@@ -0,0 +1,73 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2011 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/>.
+
+// 20.4.2.1 [tuple.cnstr] Allocator-extended constructors
+
+#include <memory>
+#include <tuple>
+
+struct MyAlloc { };
+
+struct Tag0 { };
+struct Tag1 { };
+struct Tag2 { };
+
+// A non-copyable and non-movable type
+struct Type
+{
+  typedef MyAlloc allocator_type;
+
+  explicit Type(Tag0) { }
+  Type(std::allocator_arg_t, MyAlloc, Tag1) { }
+  Type(Tag2, MyAlloc) { }
+
+  Type(const Type&) = delete;
+  Type(Type&&) = delete;
+  Type& operator=(const Type&) = delete;
+  Type& operator=(Type&&) = delete;
+};
+
+void test01()
+{
+  using std::allocator_arg;
+  using std::tuple;
+
+  MyAlloc a;
+  Tag0 tag0;
+  Tag1 tag1;
+  Tag2 tag2;
+
+  // N.B. cannot use Tag0 with uses-allocator construction, because
+  // uses_allocator<Type, MyAlloc> is true but no suitable cosntructor
+  tuple<Type>            t1(tag0);
+
+  tuple<Type>            t2(allocator_arg, a, tag1);
+  tuple<Type>            t3(allocator_arg, a, tag2);
+
+  tuple<Type, Type>      t4(allocator_arg, a, tag1, tag2);
+
+  tuple<Type, Type, Type> t5(allocator_arg, a, tag2, tag1, tag2);
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/20_util/tuple/cons/allocators.cc b/libstdc++-v3/testsuite/20_util/tuple/cons/allocators.cc
new file mode 100644 (file)
index 0000000..ae9dc8d
--- /dev/null
@@ -0,0 +1,169 @@
+// { dg-options "-std=gnu++0x" }
+
+// Copyright (C) 2011 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/>.
+
+// 20.4.2.1 [tuple.cnstr] Allocator-extended constructors
+
+#include <memory>
+#include <tuple>
+#include <testsuite_hooks.h>
+
+struct MyAlloc { };
+
+// type that can't be constructed with an allocator
+struct CannotUse
+{
+  CannotUse(int = 0, int = 0) : ok(true) { }
+
+  bool ok;
+};
+
+// type that can be constructed with an allocator
+// but which has uses_allocator == false
+struct DoesNotUse
+{
+  typedef MyAlloc allocator_type;
+
+  DoesNotUse(int = 0) : ok(true) { }
+  DoesNotUse(std::allocator_arg_t, MyAlloc, int = 0) : ok(false) { }
+  DoesNotUse(MyAlloc) : ok(false) { }
+  DoesNotUse(int, MyAlloc) : ok(false) { }
+
+  DoesNotUse(const DoesNotUse&) : ok(true) { }
+  DoesNotUse(std::allocator_arg_t, MyAlloc, const DoesNotUse&) : ok(false) { }
+  DoesNotUse(const DoesNotUse&, MyAlloc) : ok(false) { }
+
+  DoesNotUse(DoesNotUse&&) : ok(true) { }
+  DoesNotUse(std::allocator_arg_t, MyAlloc, DoesNotUse&&) : ok(false) { }
+  DoesNotUse(DoesNotUse&&, MyAlloc) : ok(false) { }
+
+  bool ok;
+};
+
+namespace std
+{
+  template<typename A> 
+    struct uses_allocator<DoesNotUse, A> : false_type { };
+}
+
+// type that can be constructed with an allocator as second argument
+struct UsesWithTag
+{
+  typedef MyAlloc allocator_type;
+
+  UsesWithTag(int = 0) : ok(false) { }
+  UsesWithTag(std::allocator_arg_t, MyAlloc, int = 0) : ok(true) { }
+  UsesWithTag(MyAlloc) : ok(false) {  }
+  UsesWithTag(int, MyAlloc) : ok(false) {  }
+
+  UsesWithTag(const UsesWithTag&) : ok(false) { }
+  UsesWithTag(std::allocator_arg_t, MyAlloc, const UsesWithTag&) : ok(true) { }
+  UsesWithTag(const UsesWithTag&, MyAlloc) : ok(false) {  }
+
+  UsesWithTag(UsesWithTag&&) : ok(false) { }
+  UsesWithTag(std::allocator_arg_t, MyAlloc, UsesWithTag&&) : ok(true) { }
+  UsesWithTag(UsesWithTag&&, MyAlloc) : ok(false) {  }
+
+  bool ok;
+};
+
+// type that can be constructed with an allocator as last argument
+struct UsesWithoutTag
+{
+  typedef MyAlloc allocator_type;
+
+  UsesWithoutTag(int = 0) : ok(false) { }
+  UsesWithoutTag(MyAlloc) : ok(true) { }
+  UsesWithoutTag(int, MyAlloc) : ok(true) { }
+
+  UsesWithoutTag(const UsesWithoutTag&) : ok(false) { }
+  UsesWithoutTag(const UsesWithoutTag&, MyAlloc) : ok(true) { }
+
+  UsesWithoutTag(UsesWithoutTag&&) : ok(false) { }
+  UsesWithoutTag(UsesWithoutTag&&, MyAlloc) : ok(true) { }
+
+  bool ok;
+};
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  using std::allocator_arg;
+  using std::tuple;
+  using std::make_tuple;
+  using std::get;
+
+  typedef CannotUse T1;
+  typedef DoesNotUse T2;
+  typedef UsesWithTag T3;
+  typedef UsesWithoutTag T4;
+  typedef tuple<T1, T2, T3, T4> test_type;
+
+  MyAlloc a;
+
+  // default construction
+  test_type t1(allocator_arg, a);
+  VERIFY( get<0>(t1).ok );
+  VERIFY( get<1>(t1).ok );
+  VERIFY( get<2>(t1).ok );
+  VERIFY( get<3>(t1).ok );
+
+  // copy construction
+  test_type t2(allocator_arg, a, t1);
+  VERIFY( get<0>(t2).ok );
+  VERIFY( get<1>(t2).ok );
+  VERIFY( get<2>(t2).ok );
+  VERIFY( get<3>(t2).ok );
+
+  // move construction
+  test_type t3(allocator_arg, a, std::move(t1));
+  VERIFY( get<0>(t3).ok );
+  VERIFY( get<1>(t3).ok );
+  VERIFY( get<2>(t3).ok );
+  VERIFY( get<3>(t3).ok );
+
+  // construction from int
+  test_type t4(allocator_arg, a, 1, 2, 3, 4);
+  VERIFY( get<0>(t4).ok );
+  VERIFY( get<1>(t4).ok );
+  VERIFY( get<2>(t4).ok );
+  VERIFY( get<3>(t4).ok );
+
+  auto ints = make_tuple(1, 2, 3, 4);
+
+  // construction from lvalue tuple of ints
+  test_type t5(allocator_arg, a, ints);
+  VERIFY( get<0>(t5).ok );
+  VERIFY( get<1>(t5).ok );
+  VERIFY( get<2>(t5).ok );
+  VERIFY( get<3>(t2).ok );
+
+  // construction from rvalue tuple of ints
+  test_type t6(allocator_arg, a, std::move(ints));
+  VERIFY( get<0>(t6).ok );
+  VERIFY( get<1>(t6).ok );
+  VERIFY( get<2>(t6).ok );
+  VERIFY( get<3>(t6).ok );
+
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc b/libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc
new file mode 100644 (file)
index 0000000..b6b706c
--- /dev/null
@@ -0,0 +1,48 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2011 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/>.
+
+// 20.4.2.1 [tuple.cnstr] Allocator-extended constructors
+
+#include <memory>
+#include <tuple>
+
+struct MyAlloc { };
+
+struct Type
+{
+  typedef MyAlloc allocator_type; // uses_allocator<Type, MyAlloc> is true
+
+  explicit Type(int) { }
+
+  Type(std::allocator_arg_t, MyAlloc) { }
+  Type(MyAlloc) { }
+};
+
+void test01()
+{
+  using std::allocator_arg;
+  using std::tuple;
+
+  MyAlloc a;
+
+  tuple<Type> t(allocator_arg, a, 1);
+}
+// { dg-error "no matching function" "" { target *-*-* } 112 }
+// { dg-excess-errors "note" }
diff --git a/libstdc++-v3/testsuite/20_util/uses_allocator/construction.cc b/libstdc++-v3/testsuite/20_util/uses_allocator/construction.cc
new file mode 100644 (file)
index 0000000..94fca79
--- /dev/null
@@ -0,0 +1,108 @@
+// { dg-options "-std=gnu++0x" }
+
+// Copyright (C) 2011 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/>.
+
+// 20.6.7.2 uses-allocator construction
+
+#include <memory>
+#include <tuple>
+#include <testsuite_hooks.h>
+
+struct MyAlloc { };
+
+// type that can't be constructed with an allocator
+struct CannotUse
+{
+  CannotUse(int) : ok(true) { }
+
+  bool ok;
+};
+
+// type that can be constructed with an allocator
+// but which has uses_allocator == false
+struct DoesNotUse
+{
+  typedef MyAlloc allocator_type;
+
+  DoesNotUse(int) : ok(true) { }
+  DoesNotUse(std::allocator_arg_t, MyAlloc, int) : ok(false) { }
+  DoesNotUse(int, MyAlloc) : ok(false) { }
+
+  bool ok;
+};
+
+namespace std
+{
+  template<typename A> 
+    struct uses_allocator<DoesNotUse, A> : false_type { };
+}
+
+// type that can be constructed with an allocator as second argument
+struct UsesWithTag
+{
+  typedef MyAlloc allocator_type;
+
+  UsesWithTag(int) : ok(false) { }
+  UsesWithTag(std::allocator_arg_t, MyAlloc, int) : ok(true) { }
+  UsesWithTag(int, MyAlloc) : ok(false) {  }
+
+  bool ok;
+};
+
+// type that can be constructed with an allocator as last argument
+struct UsesWithoutTag
+{
+  typedef MyAlloc allocator_type;
+
+  UsesWithoutTag(int) : ok(false) { }
+  UsesWithoutTag(int, MyAlloc) : ok(true) { }
+
+  bool ok;
+};
+
+
+template<typename TestType, typename... T>
+  bool test2(T... args)
+  {
+    using std::allocator_arg;
+    using std::tuple;
+    using std::get;
+
+    tuple<TestType, T...> t(allocator_arg, MyAlloc(), 1, args...);
+
+    return get<0>(t).ok;
+  }
+
+template<typename... T>
+  void test(T... args)
+  {
+    bool test __attribute__((unused)) = true;
+
+    VERIFY( test2<CannotUse>(args...) );
+    VERIFY( test2<DoesNotUse>(args...) );
+    VERIFY( test2<UsesWithTag>(args...) );
+    VERIFY( test2<UsesWithoutTag>(args...) );
+  }
+
+int main()
+{
+  test();
+  test(1);
+  test(1, 2);
+  return 0;
+}