Patchwork Fix std::pair std::is_copy_assignable behavior

login
register
mail settings
Submitter François Dumont
Date April 17, 2013, 7:10 p.m.
Message ID <516EF3B1.2050401@gmail.com>
Download mbox | patch
Permalink /patch/237346/
State New
Headers show

Comments

François Dumont - April 17, 2013, 7:10 p.m.
Hi

     Here is an other proposal to fix std::is_copy_assignable<std::pair<>>.

     This is not perfect because I have adapted it to current compiler 
behavior but it is still better than current behavior and enough to 
commit the unordered C++11 allocator adaptation afterward. It will give 
me more time to work on the Standard modification proposal to avoid the 
partial template specialization used for the moment.

     Thanks to current resolution of DR 1402 we can already define the 
move assignment operator as default, if deleted the template move 
assignment operator will be considered and potentially used instead.

2013-04-17  François Dumont <fdumont@gcc.gnu.org>

     * include/bits/stl_pair.h (operator=(const pair&)): Add noexcept
     qualification.
     (operator=(pair&&)): Use default implementation.
     (template<> operator=(const pair&)): Add noexcept
     qualification. Enable if is_assignable<T&, const U&> true for both
     parameter types.
     (template<> operator=(pair<>&&)): Add noexcept
     qualification. Enable if is_assignable<T&, U&&> true for both
     parameter types.
     (std::is_copy_assignable<>, std::is_move_assignable<>): Add
     partial specialization.
     * testsuite/20_util/pair/is_move_assignable.cc: New.
     * testsuite/20_util/pair/is_copy_assignable.cc: Likewise.
     * testsuite/20_util/pair/is_assignable.cc: Likewise.
     * testsuite/20_util/pair/is_nothrow_move_assignable.cc: Likewise.
     * testsuite/20_util/pair/assign_neg.cc: Likewise.
     * testsuite/20_util/pair/is_nothrow_copy_assignable.cc: Likewise.
     * testsuite/20_util/pair/assign.cc: Likewise.

Tested under Linux x86_64.

Ok to commit ?

François
Paolo Carlini - April 17, 2013, 7:18 p.m.
On 4/17/13 8:10 PM, François Dumont wrote:
> Hi
>
>     Here is an other proposal to fix 
> std::is_copy_assignable<std::pair<>>.
Sorry, I'm still missing something very, very basic: which behavior is 
conforming, the current one or what we would get instead? If the former, 
is there a DR arguing for the latter?

Paolo.
François Dumont - April 17, 2013, 7:43 p.m.
On 04/17/2013 09:18 PM, Paolo Carlini wrote:
> On 4/17/13 8:10 PM, François Dumont wrote:
>> Hi
>>
>>     Here is an other proposal to fix 
>> std::is_copy_assignable<std::pair<>>.
> Sorry, I'm still missing something very, very basic: which behavior is 
> conforming, the current one or what we would get instead? If the 
> former, is there a DR arguing for the latter?
>
> Paolo.
>
     The behavior I am targeting is 
std::is_copy_asignable<std::pair<const int, int>> to be std::false_type 
for instance. I have added test for many other use cases. More generally 
I need that when std::is_copy_assignable<T> is std::true_type then 
writing a = b, with a and b being T, does compile.

     Otherwise this patch just make std::pair match the Standard 
requirements like at 20.3.2.17. Do you want me to add a bug report in 
Bugzilla first ?

François
Paolo Carlini - April 17, 2013, 8:02 p.m.
Hi,

On 4/17/13 8:43 PM, François Dumont wrote:
> On 04/17/2013 09:18 PM, Paolo Carlini wrote:
>> On 4/17/13 8:10 PM, François Dumont wrote:
>>> Hi
>>>
>>>     Here is an other proposal to fix 
>>> std::is_copy_assignable<std::pair<>>.
>> Sorry, I'm still missing something very, very basic: which behavior 
>> is conforming, the current one or what we would get instead? If the 
>> former, is there a DR arguing for the latter?
>>
>> Paolo.
>>
>     The behavior I am targeting is 
> std::is_copy_asignable<std::pair<const int, int>> to be 
> std::false_type for instance. I have added test for many other use 
> cases. More generally I need that when std::is_copy_assignable<T> is 
> std::true_type then writing a = b, with a and b being T, does compile.
>
>     Otherwise this patch just make std::pair match the Standard 
> requirements like at 20.3.2.17. Do you want me to add a bug report in 
> Bugzilla first ?
I'm not talking about GCC's Bugzilla, I meant an ISO DR: if we don't 
have a DR and preferably a vague support of LWG people, I think we 
should not change the behavior of our std::is_copy_assignable only 
because it helps our implementation of other facilities.

Paolo.
François Dumont - April 17, 2013, 8:22 p.m.
On 04/17/2013 10:02 PM, Paolo Carlini wrote:
> Hi,
>
> On 4/17/13 8:43 PM, François Dumont wrote:
>> On 04/17/2013 09:18 PM, Paolo Carlini wrote:
>>> On 4/17/13 8:10 PM, François Dumont wrote:
>>>> Hi
>>>>
>>>>     Here is an other proposal to fix 
>>>> std::is_copy_assignable<std::pair<>>.
>>> Sorry, I'm still missing something very, very basic: which behavior 
>>> is conforming, the current one or what we would get instead? If the 
>>> former, is there a DR arguing for the latter?
>>>
>>> Paolo.
>>>
>>     The behavior I am targeting is 
>> std::is_copy_asignable<std::pair<const int, int>> to be 
>> std::false_type for instance. I have added test for many other use 
>> cases. More generally I need that when std::is_copy_assignable<T> is 
>> std::true_type then writing a = b, with a and b being T, does compile.
>>
>>     Otherwise this patch just make std::pair match the Standard 
>> requirements like at 20.3.2.17. Do you want me to add a bug report in 
>> Bugzilla first ?
> I'm not talking about GCC's Bugzilla, I meant an ISO DR: if we don't 
> have a DR and preferably a vague support of LWG people, I think we 
> should not change the behavior of our std::is_copy_assignable only 
> because it helps our implementation of other facilities.
>
> Paolo.
>
     I really don't get it. Is current behavior really Standard compliant ?

     I don't think so and would like to fix it. The Standard says that 
pair& operator=(const pair&) requires that both 
is_copy_assignable<first_type> and is_copy_assignable<second_type> to be 
true. With std::pair<const int, int>, is_copy_assignable<const int> is 
false and then the operator is ill formed. It is if you try to call it 
but if you check is_copy_assignable<pair<const int, int>> it says true. 
Do you see it as a correct behavior ? Do you really think that it 
requires an ISO DR ?

François
François Dumont - April 19, 2013, 8:30 p.m.
On 04/17/2013 10:02 PM, Paolo Carlini wrote:
> Hi,
>
> On 4/17/13 8:43 PM, François Dumont wrote:
>> On 04/17/2013 09:18 PM, Paolo Carlini wrote:
>>> On 4/17/13 8:10 PM, François Dumont wrote:
>>>> Hi
>>>>
>>>>     Here is an other proposal to fix 
>>>> std::is_copy_assignable<std::pair<>>.
>>> Sorry, I'm still missing something very, very basic: which behavior 
>>> is conforming, the current one or what we would get instead? If the 
>>> former, is there a DR arguing for the latter?
>>>
>>> Paolo.
>>>
>>     The behavior I am targeting is 
>> std::is_copy_asignable<std::pair<const int, int>> to be 
>> std::false_type for instance. I have added test for many other use 
>> cases. More generally I need that when std::is_copy_assignable<T> is 
>> std::true_type then writing a = b, with a and b being T, does compile.
>>
>>     Otherwise this patch just make std::pair match the Standard 
>> requirements like at 20.3.2.17. Do you want me to add a bug report in 
>> Bugzilla first ?
> I'm not talking about GCC's Bugzilla, I meant an ISO DR: if we don't 
> have a DR and preferably a vague support of LWG people, I think we 
> should not change the behavior of our std::is_copy_assignable only 
> because it helps our implementation of other facilities.
>
> Paolo.
>
Hi

     I check again the Standard and I really can't see any problem with 
the patch. As far as I understand it having std::is_copy_assignable 
being true is not a guaranty that the expression will compile but making 
std::pair is_copy_assignable friendly doesn't violate it neither.

     I also see that std::pair is already using std::enable_if to 
disable some constructors. I check the ChangeLog and it was not 
associated to a any ISO DR. I don't know why at that moment the same 
kind of modification hadn't been done for the assignment operators but 
the patch is not doing more than what has been done at that time.

     Ok to commit ?

François
Paolo Carlini - April 19, 2013, 9:17 p.m.
Hi,

"François Dumont" <frs.dumont@gmail.com> ha scritto:

>     Ok to commit ?

No, it's definitely not Ok, we don't want to add std::is_copy_assignable specializations like this.

Jon will send you more comments.

Thanks,
Paolo

Patch

Index: include/bits/stl_pair.h
===================================================================
--- include/bits/stl_pair.h	(revision 197829)
+++ include/bits/stl_pair.h	(working copy)
@@ -156,6 +156,8 @@ 
 
       pair&
       operator=(const pair& __p)
+      noexcept(__and_<is_nothrow_copy_assignable<_T1>,
+		      is_nothrow_copy_assignable<_T2>>::value)
       {
 	first = __p.first;
 	second = __p.second;
@@ -163,18 +165,15 @@ 
       }
 
       pair&
-      operator=(pair&& __p)
-      noexcept(__and_<is_nothrow_move_assignable<_T1>,
-	              is_nothrow_move_assignable<_T2>>::value)
-      {
-	first = std::forward<first_type>(__p.first);
-	second = std::forward<second_type>(__p.second);
-	return *this;
-      }
+      operator=(pair&&) = default;
 
       template<class _U1, class _U2>
-	pair&
+	typename enable_if<__and_<is_assignable<_T1&, const _U1&>,
+				  is_assignable<_T2&, const _U2&>>::value,
+			   pair&>::type
 	operator=(const pair<_U1, _U2>& __p)
+	noexcept(__and_<is_nothrow_assignable<_T1&, const _U1&>,
+			is_nothrow_assignable<_T2&, const _U2&>>::value)
 	{
 	  first = __p.first;
 	  second = __p.second;
@@ -182,8 +181,12 @@ 
 	}
 
       template<class _U1, class _U2>
-	pair&
+      	typename enable_if<__and_<is_assignable<_T1&, _U1&&>,
+      				  is_assignable<_T2&, _U2&&>>::value,
+      			   pair&>::type
 	operator=(pair<_U1, _U2>&& __p)
+	noexcept(__and_<is_nothrow_assignable<_T1&, _U1&&>,
+			is_nothrow_assignable<_T2&, _U2&&>>::value)
 	{
 	  first = std::forward<_U1>(__p.first);
 	  second = std::forward<_U2>(__p.second);
@@ -287,6 +290,19 @@ 
     { return pair<_T1, _T2>(__x, __y); }
 #endif
 
+#if __cplusplus >= 201103L
+  template<class _T1, class _T2>
+    struct is_copy_assignable<std::pair<_T1, _T2>>
+      : public __and_<std::is_copy_assignable<_T1>,
+		      std::is_copy_assignable<_T2>>::type
+    { };
+
+  template<class _T1, class _T2>
+    struct is_move_assignable<std::pair<_T1, _T2>>
+      : public __and_<std::is_move_assignable<_T1>,
+		      std::is_move_assignable<_T2>>::type
+    { };
+#endif
   /// @}
 
 _GLIBCXX_END_NAMESPACE_VERSION
Index: testsuite/20_util/pair/is_assignable.cc
===================================================================
--- testsuite/20_util/pair/is_assignable.cc	(revision 0)
+++ testsuite/20_util/pair/is_assignable.cc	(revision 0)
@@ -0,0 +1,48 @@ 
+// { dg-do compile }
+// { dg-options "-std=c++11" }
+
+// Copyright (C) 2013 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 <type_traits>
+#include <utility>
+
+struct T1
+{
+};
+
+struct T2
+{
+  T2&
+  operator=(const T1&);
+};
+
+typedef std::pair<int, int>						pt1;
+typedef std::pair<short, short>						pt2;
+typedef std::pair<int, double> pt3;
+typedef std::pair<int, T1> pt4;
+typedef std::pair<int, T2> pt5;
+
+static_assert(std::is_assignable<pt1, pt2>::value, "Error");
+static_assert(std::is_assignable<pt2, pt1>::value, "Error");
+static_assert(std::is_assignable<pt1, pt3>::value, "Error");
+static_assert(!std::is_assignable<pt4, pt1>::value, "Error");
+static_assert(!std::is_assignable<pt1, pt4>::value, "Error");
+static_assert(std::is_assignable<pt5, pt4>::value, "Error");
+static_assert(!std::is_assignable<pt4, pt5>::value, "Error");
+
+
Index: testsuite/20_util/pair/is_nothrow_move_assignable.cc
===================================================================
--- testsuite/20_util/pair/is_nothrow_move_assignable.cc	(revision 0)
+++ testsuite/20_util/pair/is_nothrow_move_assignable.cc	(revision 0)
@@ -0,0 +1,57 @@ 
+// { dg-do compile }
+// { dg-options "-std=c++11" }
+
+// Copyright (C) 2013 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 <type_traits>
+#include <utility>
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+typedef std::pair<int, int>						pt1;
+typedef std::pair<int, double>						pt2;
+typedef std::pair<NoexceptCopyAssignClass, NoexceptCopyAssignClass>	pt3;
+typedef std::pair<ExceptCopyAssignClass, ExceptCopyAssignClass>		pt4;
+typedef std::pair<ExceptCopyAssignClass, double>			pt5;
+typedef std::pair<NoexceptCopyAssignClass, ExceptCopyAssignClass>	pt6;
+typedef std::pair<const int, int>					pt7;
+typedef std::pair<int, const int>					pt8;
+typedef std::pair<NoexceptMoveAssignClass, NoexceptMoveAssignClass>	pt9;
+typedef std::pair<ExceptMoveAssignClass, ExceptMoveAssignClass>		pt10;
+typedef std::pair<ExceptMoveAssignClass, NoexceptMoveAssignClass>	pt11;
+typedef std::pair<NoexceptMoveAssignClass, ExceptMoveAssignClass>	pt12;
+typedef std::pair<int, int&>						pt13;
+typedef std::pair<int&, int&>						pt14;
+typedef std::pair<int, const int&>					pt15;
+
+static_assert(std::is_nothrow_move_assignable<pt1>::value, "Error");
+static_assert(std::is_nothrow_move_assignable<pt2>::value, "Error");
+static_assert(std::is_nothrow_move_assignable<pt3>::value, "Error");
+static_assert(!std::is_nothrow_move_assignable<pt4>::value, "Error");
+static_assert(!std::is_nothrow_move_assignable<pt5>::value, "Error");
+static_assert(!std::is_nothrow_move_assignable<pt6>::value, "Error");
+static_assert(!std::is_nothrow_move_assignable<pt7>::value, "Error");
+static_assert(!std::is_nothrow_move_assignable<pt8>::value, "Error");
+static_assert(std::is_nothrow_move_assignable<pt9>::value, "Error");
+static_assert(!std::is_nothrow_move_assignable<pt10>::value, "Error");
+static_assert(!std::is_nothrow_move_assignable<pt11>::value, "Error");
+static_assert(!std::is_nothrow_move_assignable<pt12>::value, "Error");
+static_assert(std::is_nothrow_move_assignable<pt13>::value, "Error");
+static_assert(std::is_nothrow_move_assignable<pt14>::value, "Error");
+static_assert(!std::is_nothrow_move_assignable<pt15>::value, "Error");
Index: testsuite/20_util/pair/assign_neg.cc
===================================================================
--- testsuite/20_util/pair/assign_neg.cc	(revision 0)
+++ testsuite/20_util/pair/assign_neg.cc	(revision 0)
@@ -0,0 +1,30 @@ 
+// { dg-do compile }
+// { dg-options "-std=c++11" }
+
+// Copyright (C) 2013 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 <utility>
+
+void test01()
+{
+  std::pair<const int, int> p;
+  p = p;
+  p = std::move(p);
+}
+
+// { dg-error "assignment of read-only member" "" { target *-*-* } 162 }
Index: testsuite/20_util/pair/is_nothrow_copy_assignable.cc
===================================================================
--- testsuite/20_util/pair/is_nothrow_copy_assignable.cc	(revision 0)
+++ testsuite/20_util/pair/is_nothrow_copy_assignable.cc	(revision 0)
@@ -0,0 +1,53 @@ 
+// { dg-do compile }
+// { dg-options "-std=c++11" }
+
+// Copyright (C) 2013 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 <type_traits>
+#include <utility>
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+typedef std::pair<int, int>						pt1;
+typedef std::pair<int, double>						pt2;
+typedef std::pair<const int, int>					pt3;
+typedef std::pair<int, const int>					pt4;
+typedef std::pair<int, const int>&					pt5;
+typedef std::pair<NoexceptCopyAssignClass, NoexceptCopyAssignClass>	pt6;
+typedef std::pair<ExceptCopyAssignClass, ExceptCopyAssignClass>		pt7;
+typedef std::pair<ExceptCopyAssignClass, double>			pt8;
+typedef std::pair<NoexceptCopyAssignClass, ExceptCopyAssignClass>	pt9;
+typedef std::pair<int, DeletedCopyAssignClass>				pt10;
+typedef std::pair<int, int&>						pt11;
+typedef std::pair<int&, int&>						pt12;
+typedef std::pair<int, const int&>					pt13;
+
+static_assert(std::is_nothrow_copy_assignable<pt1>::value, "Error");
+static_assert(std::is_nothrow_copy_assignable<pt2>::value, "Error");
+static_assert(!std::is_nothrow_copy_assignable<pt3>::value, "Error");
+static_assert(!std::is_nothrow_copy_assignable<pt4>::value, "Error");
+static_assert(!std::is_nothrow_copy_assignable<pt5>::value, "Error");
+static_assert(std::is_nothrow_copy_assignable<pt6>::value, "Error");
+static_assert(!std::is_nothrow_copy_assignable<pt7>::value, "Error");
+static_assert(!std::is_nothrow_copy_assignable<pt8>::value, "Error");
+static_assert(!std::is_nothrow_copy_assignable<pt9>::value, "Error");
+static_assert(!std::is_nothrow_copy_assignable<pt10>::value, "Error");
+static_assert(std::is_nothrow_copy_assignable<pt11>::value, "Error");
+static_assert(std::is_nothrow_copy_assignable<pt12>::value, "Error");
+static_assert(!std::is_nothrow_copy_assignable<pt13>::value, "Error");
Index: testsuite/20_util/pair/assign.cc
===================================================================
--- testsuite/20_util/pair/assign.cc	(revision 0)
+++ testsuite/20_util/pair/assign.cc	(revision 0)
@@ -0,0 +1,177 @@ 
+// { dg-options "-std=c++11" }
+
+// Copyright (C) 2013 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 <utility>
+#include <tuple>
+#include <testsuite_hooks.h>
+#include <testsuite_counter_type.h>
+#include <testsuite_tr1.h>
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  using __gnu_test::counter_type;
+
+  typedef std::pair<int, counter_type> ptype;
+  ptype p1(0, 0);
+  ptype p2(1, 1);
+
+  counter_type::reset();
+
+  p1 = p2;
+
+  VERIFY( p1.first == 1 );
+  VERIFY( p1.second.val == 1 );
+  VERIFY( counter_type::copy_assign_count == 1 );
+}
+
+void test02()
+{
+  bool test __attribute__((unused)) = true;
+  using __gnu_test::counter_type;
+
+  typedef std::pair<int, counter_type> ptype;
+  ptype p1(0, 0);
+  ptype p2(1, 1);
+
+  counter_type::reset();
+
+  p1 = std::move(p2);
+
+  VERIFY( p1.first == 1 );
+  VERIFY( p1.second.val == 1 );
+  VERIFY( counter_type::move_assign_count == 1 );
+}
+
+void test03()
+{
+  bool test __attribute__((unused)) = true;
+
+  typedef std::pair<int&, int&> ptype;
+  int i = 0, j = 1;
+  ptype p1(i, j);
+  VERIFY( p1.first == 0 );
+  VERIFY( p1.second == 1 );
+
+  int k = 2, l = 3;
+  ptype p2(k, l);
+  VERIFY( p2.first == 2 );
+  VERIFY( p2.second == 3 );
+
+  p1 = p2;
+
+  VERIFY( p1.first == 2 );
+  VERIFY( p1.second == 3 );
+  VERIFY( p2.first == 2 );
+  VERIFY( p2.second == 3 );
+
+  VERIFY( i == 2 );
+
+  i = 0;
+  VERIFY( p1.first == 0 );
+}
+
+void test04()
+{
+  bool test __attribute__((unused)) = true;
+
+  typedef std::pair<int&, int> ptype;
+  int i = 0;
+  ptype p1(i, 1);
+  VERIFY( p1.first == 0 );
+  VERIFY( p1.second == 1 );
+
+  int j = 2;
+  ptype p2(j, 3);
+  VERIFY( p2.first == 2 );
+  VERIFY( p2.second == 3 );
+
+  p1 = p2;
+
+  VERIFY( p1.first == 2 );
+  VERIFY( p1.second == 3 );
+  VERIFY( p2.first == 2 );
+  VERIFY( p2.second == 3 );
+
+  VERIFY( i == 2 );
+
+  i = 0;
+  VERIFY( p1.first == 0 );
+}
+
+namespace __gnu_test
+{
+  struct MyStruct
+  {
+    int _i;
+
+    MyStruct()
+      : _i() { }
+    MyStruct(int i)
+      : _i(i) { }
+    MyStruct(const MyStruct& other)
+      : _i(other._i) { }
+    MyStruct(MyStruct&& other)
+      : _i(other._i)
+    { other._i = -1; }
+
+    MyStruct&
+    operator=(const MyStruct& other)
+    { _i = other._i; }
+
+    MyStruct&
+    operator=(MyStruct&& other)
+    {
+      _i = other._i;
+      other._i = -1;
+    }
+  };
+}
+
+void test05()
+{
+  bool test __attribute__((unused)) = true;
+
+  typedef std::pair<__gnu_test::MyStruct, __gnu_test::MyStruct> ptype1;
+  typedef std::pair<__gnu_test::MyStruct, const __gnu_test::MyStruct> ptype2;
+  
+  static_assert(std::is_move_assignable<ptype1>::value, "Error");
+  static_assert(!std::is_move_assignable<ptype2>::value, "Error");
+  static_assert(std::is_assignable<ptype1&, ptype2&&>::value, "Error");
+
+  ptype1 p1(1, 2);
+  ptype2 p2(3, 4);
+
+  p1 = std::move(p2);
+
+  VERIFY( p1.first._i == 3 );
+  VERIFY( p1.second._i == 4 );
+  VERIFY( p2.first._i == -1 );
+  VERIFY( p2.second._i == 4 );
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+  test05();
+  return 0;
+}
Index: testsuite/20_util/pair/is_move_assignable.cc
===================================================================
--- testsuite/20_util/pair/is_move_assignable.cc	(revision 0)
+++ testsuite/20_util/pair/is_move_assignable.cc	(revision 0)
@@ -0,0 +1,59 @@ 
+// { dg-do compile }
+// { dg-options "-std=c++11" }
+
+// Copyright (C) 2013 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 <type_traits>
+#include <utility>
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+typedef std::pair<int, int>						pt1;
+typedef std::pair<int, double>						pt2;
+typedef std::pair<NoexceptCopyAssignClass, NoexceptCopyAssignClass>	pt3;
+typedef std::pair<ExceptCopyAssignClass, ExceptCopyAssignClass>		pt4;
+typedef std::pair<ExceptCopyAssignClass, double>			pt5;
+typedef std::pair<NoexceptCopyAssignClass, ExceptCopyAssignClass>	pt6;
+typedef std::pair<const int, int>					pt7;
+typedef std::pair<int, const int>					pt8;
+typedef std::pair<NoexceptMoveAssignClass, NoexceptMoveAssignClass>	pt9;
+typedef std::pair<ExceptMoveAssignClass, ExceptMoveAssignClass>		pt10;
+typedef std::pair<ExceptMoveAssignClass, double>			pt11;
+typedef std::pair<DeletedMoveAssignClass, ExceptMoveAssignClass>	pt12;
+typedef std::pair<DeletedMoveAssignClass, DeletedMoveAssignClass>	pt13;
+typedef std::pair<ExceptMoveAssignClass, DeletedMoveAssignClass>	pt14;
+typedef std::pair<int, int&>						pt15;
+typedef std::pair<int, const int&>					pt16;
+
+static_assert(std::is_move_assignable<pt1>::value, "Error");
+static_assert(std::is_move_assignable<pt2>::value, "Error");
+static_assert(std::is_move_assignable<pt3>::value, "Error");
+static_assert(std::is_move_assignable<pt4>::value, "Error");
+static_assert(std::is_move_assignable<pt5>::value, "Error");
+static_assert(std::is_move_assignable<pt6>::value, "Error");
+static_assert(!std::is_move_assignable<pt7>::value, "Error");
+static_assert(!std::is_move_assignable<pt8>::value, "Error");
+static_assert(std::is_move_assignable<pt9>::value, "Error");
+static_assert(std::is_move_assignable<pt10>::value, "Error");
+static_assert(std::is_move_assignable<pt11>::value, "Error");
+static_assert(!std::is_move_assignable<pt12>::value, "Error");
+static_assert(!std::is_move_assignable<pt13>::value, "Error");
+static_assert(!std::is_move_assignable<pt14>::value, "Error");
+static_assert(std::is_move_assignable<pt15>::value, "Error");
+static_assert(!std::is_move_assignable<pt16>::value, "Error");
Index: testsuite/20_util/pair/is_copy_assignable.cc
===================================================================
--- testsuite/20_util/pair/is_copy_assignable.cc	(revision 0)
+++ testsuite/20_util/pair/is_copy_assignable.cc	(revision 0)
@@ -0,0 +1,53 @@ 
+// { dg-do compile }
+// { dg-options "-std=c++11" }
+
+// Copyright (C) 2013 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 <type_traits>
+#include <utility>
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+typedef std::pair<int, int>						pt1;
+typedef std::pair<int, double>						pt2;
+typedef std::pair<const int, int>					pt3;
+typedef std::pair<int, const int>					pt4;
+//typedef std::pair<int, const int>&					pt5;
+typedef std::pair<NoexceptCopyAssignClass, NoexceptCopyAssignClass>	pt6;
+typedef std::pair<ExceptCopyAssignClass, ExceptCopyAssignClass>		pt7;
+typedef std::pair<ExceptCopyAssignClass, double>			pt8;
+typedef std::pair<NoexceptCopyAssignClass, ExceptCopyAssignClass>	pt9;
+typedef std::pair<int, DeletedCopyAssignClass>				pt10;
+typedef std::pair<int, int&>						pt11;
+typedef std::pair<int&, int&>						pt12;
+typedef std::pair<int, const int&>					pt13;
+
+static_assert(std::is_copy_assignable<pt1>::value, "Error");
+static_assert(std::is_copy_assignable<pt2>::value, "Error");
+static_assert(!std::is_copy_assignable<pt3>::value, "Error");
+static_assert(!std::is_copy_assignable<pt4>::value, "Error");
+//static_assert(!std::is_copy_assignable<pt5>::value, "Error");
+static_assert(std::is_copy_assignable<pt6>::value, "Error");
+static_assert(std::is_copy_assignable<pt7>::value, "Error");
+static_assert(std::is_copy_assignable<pt8>::value, "Error");
+static_assert(std::is_copy_assignable<pt9>::value, "Error");
+static_assert(!std::is_copy_assignable<pt10>::value, "Error");
+static_assert(std::is_copy_assignable<pt11>::value, "Error");
+static_assert(std::is_copy_assignable<pt12>::value, "Error");
+static_assert(!std::is_copy_assignable<pt13>::value, "Error");