This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] RFC: remove std::tuple<T, U> partial specialization


While fixing PR 86963 I realised we can get rid of the 2-tuple partial
specialization, and just add the relevant constructors and assignment
operators to the primary template. They're all constrained anyway, so
they won't be available except when sizeof...(_Elements) == 2.

This patch also removes the recursive evaluation of exception
specifications on the assignment operators and tuple::swap members,
just defining them on std::tuple without depending on the base
classes.

BUT it causes:

FAIL: 20_util/tuple/cons/allocator_with_any.cc execution test
/home/jwakely/src/gcc/gcc/libstdc++-v3/testsuite/20_util/tuple/cons/allocator_with_any.cc:35: void test01(): Assertion 'std::get<0>(t).empty()' failed.

where that test does:

   std::tuple<any, any> t(std::allocator_arg,
			   std::allocator<any>{});
   VERIFY(std::get<0>(t).empty());
   VERIFY(std::get<1>(t).empty());

That's because the partial specialization had a special case for
allocator_arg_t:

-      template<typename _U1, typename _U2, typename
-        enable_if<_TMC::template
-                    _MoveConstructibleTuple<_U1, _U2>()
-                  && _TMC::template
-                    _ImplicitlyMoveConvertibleTuple<_U1, _U2>()
-                 && !is_same<typename decay<_U1>::type,
-                             allocator_arg_t>::value,
-       bool>::type = true>
-        constexpr tuple(_U1&& __a1, _U2&& __a2)
-       : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }

That was added by https://gcc.gnu.org/ml/libstdc++/2016-12/msg00122.html
but I see no justification for that in the standard (and neither
libc++ nor MSFTL does anything special here, so they fail the test
too).

Ville, I'm no longer convinced by your rationale. Why is that
constraint on the 2-tuple partial specialization when the standard
doesn't say anything like "if sizeof...(Types)==2 this constructor
shall not participate in overload resolution unless decay_t<U_i> is
not allocator_arg_t" for the tuple(_UTypes&&...) constructor?

As far as I can tell, the standard says that the test is wrong.

If we think the test is right, we should report a defect. Either way,
I think this patch would be a nice simplification. We can either fix
(or just remove) the test, or constrain the primary template.


commit 6fea64cd9f546e587c7212c7b95fde0b3005f936
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Fri Aug 17 19:07:36 2018 +0100

    Remove std::tuple<T, U> partial specialization

diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index 955b853066f..7cf3184b4aa 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -298,8 +298,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       _Tuple_impl&
       operator=(_Tuple_impl&& __in)
-      noexcept(__and_<is_nothrow_move_assignable<_Head>,
-	              is_nothrow_move_assignable<_Inherited>>::value)
       {
 	_M_head(*this) = std::forward<_Head>(_M_head(__in));
 	_M_tail(*this) = std::move(_M_tail(__in));
@@ -329,8 +327,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     protected:
       void
       _M_swap(_Tuple_impl& __in)
-      noexcept(__is_nothrow_swappable<_Head>::value
-               && noexcept(_M_tail(__in)._M_swap(_M_tail(__in))))
       {
 	using std::swap;
 	swap(_M_head(*this), _M_head(__in));
@@ -429,7 +425,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       _Tuple_impl&
       operator=(_Tuple_impl&& __in)
-      noexcept(is_nothrow_move_assignable<_Head>::value)
       {
 	_M_head(*this) = std::forward<_Head>(_M_head(__in));
 	return *this;
@@ -455,7 +450,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     protected:
       void
       _M_swap(_Tuple_impl& __in)
-      noexcept(__is_nothrow_swappable<_Head>::value)
       {
 	using std::swap;
 	swap(_M_head(*this), _M_head(__in));
@@ -502,6 +496,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                      __not_<is_constructible<_Elements..., _SrcTuple>>
               >::value;
     }
+
     template<typename... _UElements>
     static constexpr bool _NotSameTuple()
     {
@@ -544,6 +539,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     {
       return true;
     }
+
     template<typename... _UElements>
     static constexpr bool _NotSameTuple()
     {
@@ -740,6 +736,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         explicit constexpr tuple(tuple<_UElements...>&& __in)
         : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
 
+      // Shortcut for constraining the constructors taking pairs.
+      using _TP = _TC<sizeof...(_Elements) == 2, _Elements...>;
+
+      template<typename _U1, typename _U2,
+	  __enable_if_t<_TP::template _ConstructibleTuple<_U1, _U2>()
+	    && _TP::template _ImplicitlyConvertibleTuple<_U1, _U2>(),
+	  bool> = true>
+	constexpr tuple(const pair<_U1, _U2>& __in)
+	: _Inherited(__in.first, __in.second) { }
+
+      template<typename _U1, typename _U2,
+        __enable_if_t<_TP::template _ConstructibleTuple<_U1, _U2>()
+	    && ! _TP::template _ImplicitlyConvertibleTuple<_U1, _U2>(),
+	  bool> = false>
+	explicit constexpr tuple(const pair<_U1, _U2>& __in)
+	: _Inherited(__in.first, __in.second) { }
+
+      template<typename _U1, typename _U2,
+	__enable_if_t<_TP::template _MoveConstructibleTuple<_U1, _U2>()
+	    && _TP::template _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+	  bool> = true>
+	constexpr tuple(pair<_U1, _U2>&& __in)
+	: _Inherited(std::forward<_U1>(__in.first),
+		     std::forward<_U2>(__in.second)) { }
+
+      template<typename _U1, typename _U2,
+        __enable_if_t<_TP::template _MoveConstructibleTuple<_U1, _U2>()
+	    && ! _TP::template _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+	  bool> = false>
+	explicit constexpr tuple(pair<_U1, _U2>&& __in)
+	: _Inherited(std::forward<_U1>(__in.first),
+		     std::forward<_U2>(__in.second)) { }
+
       // Allocator-extended constructors.
 
       template<typename _Alloc>
@@ -764,8 +793,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                  && !_TCC<_Dummy>::template
                    _ImplicitlyConvertibleTuple<_Elements...>(),
                bool>::type=false>
-	explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
-                       const _Elements&... __elements)
+	explicit
+	tuple(allocator_arg_t __tag, const _Alloc& __a,
+              const _Elements&... __elements)
 	: _Inherited(__tag, __a, __elements...) { }
 
       template<typename _Alloc, typename... _UElements, typename
@@ -785,7 +815,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                   && !_TMC<_UElements...>::template
                     _ImplicitlyMoveConvertibleTuple<_UElements...>(),
         bool>::type=false>
-	explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+	explicit
+	tuple(allocator_arg_t __tag, const _Alloc& __a,
 	      _UElements&&... __elements)
 	: _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
         { }
@@ -822,7 +853,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                   && _TNTC<_Dummy>::template
                     _NonNestedTuple<tuple<_UElements...>&&>(),
         bool>::type=false>
-	explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+	explicit
+	tuple(allocator_arg_t __tag, const _Alloc& __a,
 	      const tuple<_UElements...>& __in)
 	: _Inherited(__tag, __a,
 	             static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
@@ -852,12 +884,53 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                   && _TNTC<_Dummy>::template
                     _NonNestedTuple<tuple<_UElements...>&&>(),
         bool>::type=false>
-	explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+	explicit
+	tuple(allocator_arg_t __tag, const _Alloc& __a,
 	      tuple<_UElements...>&& __in)
 	: _Inherited(__tag, __a,
 	             static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
 	{ }
 
+      template<typename _Alloc, typename _U1, typename _U2,
+	  __enable_if_t<_TP::template _ConstructibleTuple<_U1, _U2>()
+	    && _TP::template _ImplicitlyConvertibleTuple<_U1, _U2>(),
+	  bool> = true>
+        constexpr
+	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,
+        __enable_if_t<_TP::template _ConstructibleTuple<_U1, _U2>()
+	    && ! _TP::template _ImplicitlyConvertibleTuple<_U1, _U2>(),
+	  bool> = false>
+        explicit constexpr
+	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,
+	__enable_if_t<_TP::template _MoveConstructibleTuple<_U1, _U2>()
+	    && _TP::template _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+	  bool> = true>
+        constexpr
+	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))
+	{ }
+
+      template<typename _Alloc, typename _U1, typename _U2,
+        __enable_if_t<_TP::template _MoveConstructibleTuple<_U1, _U2>()
+	    && ! _TP::template _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+	  bool> = false>
+        explicit constexpr
+	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=(typename conditional<__assignable<const _Elements&...>(),
 				     const tuple&,
@@ -896,9 +969,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  return *this;
 	}
 
+      template<typename _U1, typename _U2>
+	__enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
+	operator=(const pair<_U1, _U2>& __in)
+	noexcept(__nothrow_assignable<const _U1&, const _U2&>())
+	{
+	  this->_M_head(*this) = __in.first;
+	  this->_M_tail(*this)._M_head(*this) = __in.second;
+	  return *this;
+	}
+
+      template<typename _U1, typename _U2>
+	__enable_if_t<__assignable<_U1, _U2>(), tuple&>
+	operator=(pair<_U1, _U2>&& __in)
+	noexcept(__nothrow_assignable<_U1, _U2>())
+	{
+	  this->_M_head(*this) = std::forward<_U1>(__in.first);
+	  this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
+	  return *this;
+	}
+
       void
       swap(tuple& __in)
-      noexcept(noexcept(__in._M_swap(__in)))
+      noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value)
       { _Inherited::_M_swap(__in); }
     };
 
@@ -931,389 +1024,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	tuple(allocator_arg_t, const _Alloc&, const tuple&) { }
     };
 
-  /// Partial specialization, 2-element tuple.
-  /// Includes construction and assignment from a pair.
-  template<typename _T1, typename _T2>
-    class tuple<_T1, _T2>
-    : public _Tuple_impl<0, _T1, _T2>,
-      private __tuple_base<tuple<_T1, _T2>>
-    {
-      typedef _Tuple_impl<0, _T1, _T2> _Inherited;
-
-      template<typename _U1, typename _U2>
-	static constexpr bool __assignable()
-	{
-	  return __and_<is_assignable<_T1&, _U1>,
-			is_assignable<_T2&, _U2>>::value;
-	}
-
-      template<typename _U1, typename _U2>
-	static constexpr bool __nothrow_assignable()
-	{
-	  return __and_<is_nothrow_assignable<_T1&, _U1>,
-			is_nothrow_assignable<_T2&, _U2>>::value;
-	}
-
-    public:
-      template <typename _U1 = _T1,
-                typename _U2 = _T2,
-                typename enable_if<__and_<
-                                     __is_implicitly_default_constructible<_U1>,
-                                     __is_implicitly_default_constructible<_U2>>
-                                   ::value, bool>::type = true>
-	constexpr tuple()
-	: _Inherited() { }
-
-      template <typename _U1 = _T1,
-                typename _U2 = _T2,
-                typename enable_if<
-                  __and_<
-                    is_default_constructible<_U1>,
-                    is_default_constructible<_U2>,
-                    __not_<
-                      __and_<__is_implicitly_default_constructible<_U1>,
-                             __is_implicitly_default_constructible<_U2>>>>
-                  ::value, bool>::type = false>
-	explicit constexpr tuple()
-	: _Inherited() { }
-
-      // Shortcut for the cases where constructors taking _T1, _T2
-      // need to be constrained.
-      template<typename _Dummy> using _TCC =
-        _TC<is_same<_Dummy, void>::value, _T1, _T2>;
-
-      template<typename _Dummy = void, typename
-               enable_if<_TCC<_Dummy>::template
-                           _ConstructibleTuple<_T1, _T2>()
-                         && _TCC<_Dummy>::template
-                           _ImplicitlyConvertibleTuple<_T1, _T2>(),
-	bool>::type = true>
-        constexpr tuple(const _T1& __a1, const _T2& __a2)
-        : _Inherited(__a1, __a2) { }
-
-      template<typename _Dummy = void, typename
-               enable_if<_TCC<_Dummy>::template
-                           _ConstructibleTuple<_T1, _T2>()
-                         && !_TCC<_Dummy>::template
-                           _ImplicitlyConvertibleTuple<_T1, _T2>(),
-	bool>::type = false>
-        explicit constexpr tuple(const _T1& __a1, const _T2& __a2)
-        : _Inherited(__a1, __a2) { }
-
-      // Shortcut for the cases where constructors taking _U1, _U2
-      // need to be constrained.
-      using _TMC = _TC<true, _T1, _T2>;
-
-      template<typename _U1, typename _U2, typename
-        enable_if<_TMC::template
-                    _MoveConstructibleTuple<_U1, _U2>()
-                  && _TMC::template
-                    _ImplicitlyMoveConvertibleTuple<_U1, _U2>()
-	          && !is_same<typename decay<_U1>::type,
-			      allocator_arg_t>::value,
-	bool>::type = true>
-        constexpr tuple(_U1&& __a1, _U2&& __a2)
-	: _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
-
-      template<typename _U1, typename _U2, typename
-        enable_if<_TMC::template
-                    _MoveConstructibleTuple<_U1, _U2>()
-                  && !_TMC::template
-                    _ImplicitlyMoveConvertibleTuple<_U1, _U2>()
-	          && !is_same<typename decay<_U1>::type,
-			      allocator_arg_t>::value,
-	bool>::type = false>
-        explicit constexpr tuple(_U1&& __a1, _U2&& __a2)
-	: _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
-
-      constexpr tuple(const tuple&) = default;
-
-      constexpr tuple(tuple&&) = default;
-
-      template<typename _U1, typename _U2, typename
-        enable_if<_TMC::template
-                    _ConstructibleTuple<_U1, _U2>()
-                  && _TMC::template
-                    _ImplicitlyConvertibleTuple<_U1, _U2>(),
-	bool>::type = true>
-        constexpr tuple(const tuple<_U1, _U2>& __in)
-	: _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
-
-      template<typename _U1, typename _U2, typename
-        enable_if<_TMC::template
-                    _ConstructibleTuple<_U1, _U2>()
-                  && !_TMC::template
-                    _ImplicitlyConvertibleTuple<_U1, _U2>(),
-	bool>::type = false>
-        explicit constexpr tuple(const tuple<_U1, _U2>& __in)
-	: _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
-
-      template<typename _U1, typename _U2, typename
-        enable_if<_TMC::template
-                    _MoveConstructibleTuple<_U1, _U2>()
-                  && _TMC::template
-                    _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
-	bool>::type = true>
-        constexpr tuple(tuple<_U1, _U2>&& __in)
-	: _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
-
-      template<typename _U1, typename _U2, typename
-        enable_if<_TMC::template
-                    _MoveConstructibleTuple<_U1, _U2>()
-                  && !_TMC::template
-                    _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
-	bool>::type = false>
-        explicit constexpr tuple(tuple<_U1, _U2>&& __in)
-	: _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
-
-      template<typename _U1, typename _U2, typename
-        enable_if<_TMC::template
-                    _ConstructibleTuple<_U1, _U2>()
-                  && _TMC::template
-                    _ImplicitlyConvertibleTuple<_U1, _U2>(),
-	bool>::type = true>
-        constexpr tuple(const pair<_U1, _U2>& __in)
-	: _Inherited(__in.first, __in.second) { }
-
-      template<typename _U1, typename _U2, typename
-        enable_if<_TMC::template
-                    _ConstructibleTuple<_U1, _U2>()
-                  && !_TMC::template
-                    _ImplicitlyConvertibleTuple<_U1, _U2>(),
-	bool>::type = false>
-        explicit constexpr tuple(const pair<_U1, _U2>& __in)
-	: _Inherited(__in.first, __in.second) { }
-
-      template<typename _U1, typename _U2, typename
-        enable_if<_TMC::template
-                    _MoveConstructibleTuple<_U1, _U2>()
-                  && _TMC::template
-                    _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
-	bool>::type = true>
-        constexpr tuple(pair<_U1, _U2>&& __in)
-	: _Inherited(std::forward<_U1>(__in.first),
-		     std::forward<_U2>(__in.second)) { }
-
-      template<typename _U1, typename _U2, typename
-        enable_if<_TMC::template
-                    _MoveConstructibleTuple<_U1, _U2>()
-                  && !_TMC::template
-                    _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
-	bool>::type = false>
-        explicit constexpr tuple(pair<_U1, _U2>&& __in)
-	: _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, typename _Dummy = void,
-               typename enable_if<
-                 _TCC<_Dummy>::template
-                   _ConstructibleTuple<_T1, _T2>()
-                 && _TCC<_Dummy>::template
-                   _ImplicitlyConvertibleTuple<_T1, _T2>(),
-               bool>::type=true>
-
-	tuple(allocator_arg_t __tag, const _Alloc& __a,
-	      const _T1& __a1, const _T2& __a2)
-	: _Inherited(__tag, __a, __a1, __a2) { }
-
-      template<typename _Alloc, typename _Dummy = void,
-               typename enable_if<
-                 _TCC<_Dummy>::template
-                   _ConstructibleTuple<_T1, _T2>()
-                 && !_TCC<_Dummy>::template
-                   _ImplicitlyConvertibleTuple<_T1, _T2>(),
-               bool>::type=false>
-
-	explicit 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, typename
-        enable_if<_TMC::template
-                    _MoveConstructibleTuple<_U1, _U2>()
-                  && _TMC::template
-                    _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
-	bool>::type = true>
-	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, typename _U1, typename _U2, typename
-        enable_if<_TMC::template
-                    _MoveConstructibleTuple<_U1, _U2>()
-                  && !_TMC::template
-                    _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
-	bool>::type = false>
-	explicit 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, typename
-        enable_if<_TMC::template
-                    _ConstructibleTuple<_U1, _U2>()
-                  && _TMC::template
-                    _ImplicitlyConvertibleTuple<_U1, _U2>(),
-	bool>::type = true>
-	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, typename
-        enable_if<_TMC::template
-                    _ConstructibleTuple<_U1, _U2>()
-                  && !_TMC::template
-                    _ImplicitlyConvertibleTuple<_U1, _U2>(),
-	bool>::type = false>
-	explicit 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, typename
-        enable_if<_TMC::template
-                    _MoveConstructibleTuple<_U1, _U2>()
-                  && _TMC::template
-                    _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
-	bool>::type = true>
-	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, typename
-        enable_if<_TMC::template
-                    _MoveConstructibleTuple<_U1, _U2>()
-                  && !_TMC::template
-                    _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
-	bool>::type = false>
-	explicit 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, typename
-        enable_if<_TMC::template
-                    _ConstructibleTuple<_U1, _U2>()
-                  && _TMC::template
-                    _ImplicitlyConvertibleTuple<_U1, _U2>(),
-	bool>::type = true>
-        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, typename
-        enable_if<_TMC::template
-                    _ConstructibleTuple<_U1, _U2>()
-                  && !_TMC::template
-                    _ImplicitlyConvertibleTuple<_U1, _U2>(),
-	bool>::type = false>
-        explicit 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, typename
-        enable_if<_TMC::template
-                    _MoveConstructibleTuple<_U1, _U2>()
-                  && _TMC::template
-                    _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
-	bool>::type = true>
-        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)) { }
-
-      template<typename _Alloc, typename _U1, typename _U2, typename
-        enable_if<_TMC::template
-                    _MoveConstructibleTuple<_U1, _U2>()
-                  && !_TMC::template
-                    _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
-	bool>::type = false>
-        explicit 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=(typename conditional<__assignable<const _T1&, const _T2&>(),
-				     const tuple&,
-				     const __nonesuch_no_braces&>::type __in)
-      noexcept(__nothrow_assignable<const _T1&, const _T2&>())
-      {
-	static_cast<_Inherited&>(*this) = __in;
-	return *this;
-      }
-
-      tuple&
-      operator=(typename conditional<__assignable<_T1, _T2>(),
-				     tuple&&,
-				     __nonesuch_no_braces&&>::type __in)
-      noexcept(__nothrow_assignable<_T1, _T2>())
-      {
-	static_cast<_Inherited&>(*this) = std::move(__in);
-	return *this;
-      }
-
-      template<typename _U1, typename _U2>
-	__enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
-	operator=(const tuple<_U1, _U2>& __in)
-	noexcept(__nothrow_assignable<const _U1&, const _U2&>())
-	{
-	  static_cast<_Inherited&>(*this) = __in;
-	  return *this;
-	}
-
-      template<typename _U1, typename _U2>
-	__enable_if_t<__assignable<_U1, _U2>(), tuple&>
-	operator=(tuple<_U1, _U2>&& __in)
-	noexcept(__nothrow_assignable<_U1, _U2>())
-	{
-	  static_cast<_Inherited&>(*this) = std::move(__in);
-	  return *this;
-	}
-
-      template<typename _U1, typename _U2>
-	__enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
-	operator=(const pair<_U1, _U2>& __in)
-	noexcept(__nothrow_assignable<const _U1&, const _U2&>())
-	{
-	  this->_M_head(*this) = __in.first;
-	  this->_M_tail(*this)._M_head(*this) = __in.second;
-	  return *this;
-	}
-
-      template<typename _U1, typename _U2>
-	__enable_if_t<__assignable<_U1, _U2>(), tuple&>
-	operator=(pair<_U1, _U2>&& __in)
-	noexcept(__nothrow_assignable<_U1, _U2>())
-	{
-	  this->_M_head(*this) = std::forward<_U1>(__in.first);
-	  this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
-	  return *this;
-	}
-
-      void
-      swap(tuple& __in)
-      noexcept(noexcept(__in._M_swap(__in)))
-      { _Inherited::_M_swap(__in); }
-    };
-
-
   /// class tuple_size
   template<typename... _Elements>
     struct tuple_size<tuple<_Elements...>>

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]