Patchwork Fix std::pair std::is_copy_assignable behavior

login
register
mail settings
Submitter François Dumont
Date April 13, 2013, 7:21 p.m.
Message ID <5169B02E.1060802@gmail.com>
Download mbox | patch
Permalink /patch/236389/
State New
Headers show

Comments

François Dumont - April 13, 2013, 7:21 p.m.
Hider

     Here is a patch already posted to libstdc++ mailing but I am 
resending following libstdc++ maintainers advises to add gcc-patches 
mailing list.

     This patch proposal is to fix the behavior of std::pair regarding 
the std::is_*_assignable meta programming functions.

     As announced it is requiring a compiler patch to extend DR 1402 
resolution to all defaulted methods.

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

     * call.c (joust): Extend DR 1402 to all defaulted methods.

     This modification is mandatory so that pair& operator=(const pair&) 
can be defaulted whereas leaving gcc consider the other operator= in 
some situations like std::pair<int&, int>. This way, with usage of 
std::enable_if on the template operator=, we can control when p1= p2 is 
a valid expression resulting in a correct behavior of 
std::is_copy_assignable.

     For the moment I preferred to add a dg-require-normal-mode option 
in the single test that fail to compile because of the compiler 
modification.

Does DR 1402 resolution generalization need a Standard committee 
validation first ?

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

     * include/bits/stl_pair.h (operator=(const pair&)): Defaulted.
     (operator=(pair&&)): Likewise.
     (template<> operator=(const pair&)): Add noexcept
     qualification. Enable if is_assignable<T&, const U&> true for both
     parameters.
     (template<> operator=(pair<>&&)): Add noexcept
     qualification. Enable if is_assignable<T&, U&&> true for both
     parameters.
     * testsuite/23_containers/unordered_set/55043.cc: Add
     dg-require-normal-mode.
     * 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.

François
Paolo Carlini - April 13, 2013, 8:31 p.m.
On 04/13/2013 09:21 PM, François Dumont wrote:
> Does DR 1402 resolution generalization need a Standard committee 
> validation first ?
In my opinion, it's much more clear to send the C++ front-end patch 
*separately* together with a simple C++-only (no library) testcase. I 
would also CC Jason.

Paolo.
Gabriel Dos Reis - April 14, 2013, 1:33 a.m.
> Does DR 1402 resolution generalization need a Standard committee validation
> first ?

I cannot see why we would want otherwise :-)

-- Gaby
François Dumont - April 14, 2013, 12:32 p.m.
On 04/14/2013 03:33 AM, Gabriel Dos Reis wrote:
>> Does DR 1402 resolution generalization need a Standard committee validation
>> first ?
> I cannot see why we would want otherwise :-)
>
> -- Gaby
>
I rather wonder if gcc only accept modifications that has been validated 
by the Standard committee first or if we can first apply the 
modification to challenge it as much as possible while discussing about 
it at the same time.

Of course I ask because the compiler modification has a relatively 
limited (bad) impact like libstdc++ testsuite have shown.

Patch

Index: include/bits/stl_pair.h
===================================================================
--- include/bits/stl_pair.h	(revision 197829)
+++ include/bits/stl_pair.h	(working copy)
@@ -155,26 +155,18 @@ 
         pair(piecewise_construct_t, tuple<_Args1...>, tuple<_Args2...>);
 
       pair&
-      operator=(const pair& __p)
-      {
-	first = __p.first;
-	second = __p.second;
-	return *this;
-      }
+      operator=(const pair&) = default;
 
       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 +174,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);
Index: testsuite/23_containers/unordered_set/55043.cc
===================================================================
--- testsuite/23_containers/unordered_set/55043.cc	(revision 197829)
+++ testsuite/23_containers/unordered_set/55043.cc	(working copy)
@@ -1,5 +1,6 @@ 
 // { dg-options "-std=gnu++0x" }
 // { dg-do compile }
+// { dg-require-normal-mode "" }
 
 // Copyright (C) 2013 Free Software Foundation, Inc.
 //
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,29 @@ 
+// { 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; // { dg-error "use of deleted function" }
+}
+
+// { dg-error "can't use default assignment operator" "" { target *-*-* } 158 }
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,124 @@ 
+// { 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 <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 );
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+  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");
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");
+
+