Patchwork [v3] Fix libstdc++/45228

login
register
mail settings
Submitter Paolo Carlini
Date Aug. 10, 2010, 7:22 a.m.
Message ID <4C60FE2D.50903@oracle.com>
Download mbox | patch
Permalink /patch/61340/
State New
Headers show

Comments

Paolo Carlini - Aug. 10, 2010, 7:22 a.m.
Hi,

tested x86_64-linux, committed to mainline. Maybe we can even better
here, but the cleanest solution I can see is adding constrains for
sizeof...(_UElements) == sizeof...(_Elements) to the converting
constructors and assignment operators of the primary template (something
that the FCD even encourages) and adding a quite short tuple
specialization for single element. That also allows to resolve the long
standing XXX fixme.

Paolo.
2010-08-10  Paolo Carlini  <paolo.carlini@oracle.com>

	PR libstdc++/45228
	* include/std/tuple (tuple<typename... _Elements>): Constrain
	converting constructors and assignment operators with
	sizeof...(_UElements) == sizeof...(_Elements).
	(tuple(tuple<_UElements...>&): Remove.
	(tuple<typename _T1>): Add.
	* testsuite/20_util/tuple/cons/45228.cc: New.
	* testsuite/20_util/tuple/cons/converting.cc: Likewise.
	* testsuite/20_util/weak_ptr/comparison/cmp_neg.cc: Adjust
	dg-error line number.

	* include/std/tuple (_Tuple_impl<>::_Tuple_impl(const _Tuple_impl&)):
	Defaulted.

	* include/std/tuple (tuple<typename _T1, typename _T2>
	::operator=(pair<_U1, _U2>&&)): Use forward.

Patch

Index: include/std/tuple
===================================================================
--- include/std/tuple	(revision 163038)
+++ include/std/tuple	(working copy)
@@ -160,8 +160,7 @@ 
 	: _Inherited(std::forward<_UTail>(__tail)...),
 	  _Base(std::forward<_UHead>(__head)) { }
 
-      _Tuple_impl(const _Tuple_impl& __in)
-      : _Inherited(__in._M_tail()), _Base(__in._M_head()) { }
+      _Tuple_impl(const _Tuple_impl&) = default;
 
       _Tuple_impl(_Tuple_impl&& __in)
       : _Inherited(std::move(__in._M_tail())),
@@ -233,7 +232,9 @@ 
       tuple(const _Elements&... __elements)
       : _Inherited(__elements...) { }
 
-      template<typename... _UElements>
+      template<typename... _UElements, typename = typename
+	       std::enable_if<sizeof...(_UElements)
+			      == sizeof...(_Elements)>::type>
         explicit
         tuple(_UElements&&... __elements)
 	: _Inherited(std::forward<_UElements>(__elements)...) {	}
@@ -243,21 +244,19 @@ 
       tuple(tuple&& __in)
       : _Inherited(static_cast<_Inherited&&>(__in)) { }
 
-      template<typename... _UElements>
+      template<typename... _UElements, typename = typename
+	       std::enable_if<sizeof...(_UElements)
+			      == sizeof...(_Elements)>::type>
         tuple(const tuple<_UElements...>& __in)
 	: _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
 	{ }
 
-      template<typename... _UElements>
+      template<typename... _UElements, typename = typename
+	       std::enable_if<sizeof...(_UElements)
+			      == sizeof...(_Elements)>::type>
         tuple(tuple<_UElements...>&& __in)
-	: _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
+        : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
 
-      // XXX http://gcc.gnu.org/ml/libstdc++/2008-02/msg00047.html
-      template<typename... _UElements>
-        tuple(tuple<_UElements...>& __in)
-	: _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
-	{ }
-
       tuple&
       operator=(const tuple& __in)
       {
@@ -272,7 +271,9 @@ 
 	return *this;
       }
 
-      template<typename... _UElements>
+      template<typename... _UElements, typename = typename
+	       std::enable_if<sizeof...(_UElements)
+			      == sizeof...(_Elements)>::type>
         tuple&
         operator=(const tuple<_UElements...>& __in)
         {
@@ -280,7 +281,9 @@ 
 	  return *this;
 	}
 
-      template<typename... _UElements>
+      template<typename... _UElements, typename = typename
+	       std::enable_if<sizeof...(_UElements)
+			      == sizeof...(_Elements)>::type>
         tuple&
         operator=(tuple<_UElements...>&& __in)
         {
@@ -293,7 +296,6 @@ 
       { _Inherited::_M_swap_impl(__in); }
     };
 
-
   template<>  
     class tuple<>
     {
@@ -385,8 +387,8 @@ 
         tuple&
         operator=(pair<_U1, _U2>&& __in)
         {
-	  this->_M_head() = std::move(__in.first);
-	  this->_M_tail()._M_head() = std::move(__in.second);
+	  this->_M_head() = std::forward<_U1>(__in.first);
+	  this->_M_tail()._M_head() = std::forward<_U2>(__in.second);
 	  return *this;
 	}
 
@@ -399,7 +401,75 @@ 
       }
     };
 
+  /// tuple (1-element).
+  template<typename _T1>
+    class tuple<_T1> : public _Tuple_impl<0, _T1>
+    {
+      typedef _Tuple_impl<0, _T1> _Inherited;
 
+    public:
+      tuple()
+      : _Inherited() { }
+
+      explicit
+      tuple(const _T1& __a1)
+      : _Inherited(__a1) { }
+
+      template<typename _U1, typename = typename
+	       std::enable_if<std::is_convertible<_U1, _T1>::value>::type>
+        explicit
+        tuple(_U1&& __a1)
+	: _Inherited(std::forward<_U1>(__a1)) { }
+
+      tuple(const tuple&) = default;
+
+      tuple(tuple&& __in)
+      : _Inherited(static_cast<_Inherited&&>(__in)) { }
+
+      template<typename _U1>
+        tuple(const tuple<_U1>& __in)
+        : _Inherited(static_cast<const _Tuple_impl<0, _U1>&>(__in)) { }
+
+      template<typename _U1>
+        tuple(tuple<_U1>&& __in)
+	: _Inherited(static_cast<_Tuple_impl<0, _U1>&&>(__in)) { }
+
+      tuple&
+      operator=(const tuple& __in)
+      {
+	static_cast<_Inherited&>(*this) = __in;
+	return *this;
+      }
+
+      tuple&
+      operator=(tuple&& __in)
+      {
+	static_cast<_Inherited&>(*this) = std::move(__in);
+	return *this;
+      }
+
+      template<typename _U1>
+        tuple&
+        operator=(const tuple<_U1>& __in)
+        {
+	  static_cast<_Inherited&>(*this) = __in;
+	  return *this;
+	}
+
+      template<typename _U1>
+        tuple&
+        operator=(tuple<_U1>&& __in)
+        {
+	  static_cast<_Inherited&>(*this) = std::move(__in);
+	  return *this;
+	}
+
+      void
+      swap(tuple& __in)
+      { _Inherited::_M_swap_impl(__in); }
+    };
+
+
   /// Gives the type of the ith element of a given tuple type.
   template<std::size_t __i, typename _Tp>
     struct tuple_element;
Index: testsuite/20_util/tuple/cons/converting.cc
===================================================================
--- testsuite/20_util/tuple/cons/converting.cc	(revision 0)
+++ testsuite/20_util/tuple/cons/converting.cc	(revision 0)
@@ -0,0 +1,37 @@ 
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2010 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/>.
+
+#include <tuple>
+
+// http://gcc.gnu.org/ml/libstdc++/2008-02/msg00047.html
+std::tuple<int> ts1;
+std::tuple<unsigned> tu1(ts1);
+
+std::tuple<int, int> ts2;
+std::tuple<unsigned, unsigned> tu2(ts2);
+
+std::tuple<int, int, int> ts3;
+std::tuple<unsigned, unsigned, unsigned> tu3(ts3);
+
+std::tuple<int, unsigned> tm2;
+std::tuple<unsigned, int> tm2_(tm2);
+
+std::tuple<int, unsigned, int> tm3;
+std::tuple<unsigned, int, unsigned> tm3_(tm3);
Index: testsuite/20_util/tuple/cons/45228.cc
===================================================================
--- testsuite/20_util/tuple/cons/45228.cc	(revision 0)
+++ testsuite/20_util/tuple/cons/45228.cc	(revision 0)
@@ -0,0 +1,43 @@ 
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2010 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/>.
+
+#include <tuple>
+
+typedef std::tuple<int>           Tuple_1;
+typedef std::tuple<int, int>      Tuple_2;
+typedef std::tuple<int, int, int> Tuple_3;
+
+      Tuple_1 A_1() { return Tuple_1(); }
+const Tuple_1 B_1() { return Tuple_1(); }
+
+      Tuple_2 A_2() { return Tuple_2(); }
+const Tuple_2 B_2() { return Tuple_2(); }
+
+      Tuple_3 A_3() { return Tuple_3(); }
+const Tuple_3 B_3() { return Tuple_3(); }
+
+Tuple_1 test_A_1(A_1());
+Tuple_1 test_B_1(B_1());
+
+Tuple_2 test_A_2(A_2());
+Tuple_2 test_B_2(B_2());
+
+Tuple_3 test_A_3(A_3());
+Tuple_3 test_B_3(B_3());
Index: testsuite/20_util/weak_ptr/comparison/cmp_neg.cc
===================================================================
--- testsuite/20_util/weak_ptr/comparison/cmp_neg.cc	(revision 163038)
+++ testsuite/20_util/weak_ptr/comparison/cmp_neg.cc	(working copy)
@@ -44,7 +44,7 @@ 
 // { dg-warning "note" "" { target *-*-* } 324 }
 // { dg-warning "note" "" { target *-*-* } 423 }
 // { dg-warning "note" "" { target *-*-* } 862 }
-// { dg-warning "note" "" { target *-*-* } 510 }
+// { dg-warning "note" "" { target *-*-* } 580 }
 // { dg-warning "note" "" { target *-*-* } 1027 }
 // { dg-warning "note" "" { target *-*-* } 340 }
 // { dg-warning "note" "" { target *-*-* } 290 }