Re: [v3 PATCH] LWG 2766, LWG 2749

2016-12-08 Thread Jonathan Wakely

On 26/11/16 14:47 +0200, Ville Voutilainen wrote:

--- a/libstdc++-v3/include/std/array
+++ b/libstdc++-v3/include/std/array
@@ -287,6 +287,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two)
noexcept(noexcept(__one.swap(__two)))
{ __one.swap(__two); }
+#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
+  template
+inline
+typename enable_if<
+  !_GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::_Is_swappable::value>::type
+swap(array<_Tp, _Nm>&, array<_Tp, _Nm>&) = delete;
+#endif

  template
constexpr _Tp&


We need to also delete std::swap for the debug mode version of
array.

I'm removing the 'inline' keyword on these deleted overloads, because
it doesn't do anything.

* include/debug/array (swap): Add deleted overload.
* include/bits/stl_pair.h (swap): Remove redundant inline keyword
from deleted overload.
* include/bits/unique_ptr.h (swap): Likewise.
* include/std/array (swap): Likewise.
* include/std/optional (swap): Likewise.
* include/std/tuple (swap): Likewise.
* include/std/variant (swap): Likewise.
* testsuite/23_containers/array/tuple_interface/get_debug_neg.cc:
Adjust dg-error line numbers.
   * testsuite/23_containers/array/tuple_interface/get_neg.cc: Likewise.
* testsuite/23_containers/array/tuple_interface/
tuple_element_debug_neg.cc: Likewise.
   * testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc:
   Likewise.

Tested powerpc64le-linux, committed to trunk.

commit e217847dc333862d70cf8376c09c0b96296d6b54
Author: Jonathan Wakely 
Date:   Thu Dec 8 12:03:39 2016 +

Delete std::swap for debug mode array

	* include/debug/array (swap): Add deleted overload.
	* include/bits/stl_pair.h (swap): Remove redundant inline keyword
	from deleted overload.
	* include/bits/unique_ptr.h (swap): Likewise.
	* include/std/array (swap): Likewise.
	* include/std/optional (swap): Likewise.
	* include/std/tuple (swap): Likewise.
	* include/std/variant (swap): Likewise.
	* testsuite/23_containers/array/tuple_interface/get_debug_neg.cc:
	Adjust dg-error line numbers.
	* testsuite/23_containers/array/tuple_interface/get_neg.cc: Likewise.
	* testsuite/23_containers/array/tuple_interface/
	tuple_element_debug_neg.cc: Likewise.
	* testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc:
	Likewise.

diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h
index 981dbeb..01c7134 100644
--- a/libstdc++-v3/include/bits/stl_pair.h
+++ b/libstdc++-v3/include/bits/stl_pair.h
@@ -481,7 +481,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
   template
-inline
 typename enable_if,
 			   __is_swappable<_T2>>::value>::type
 swap(pair<_T1, _T2>&, pair<_T1, _T2>&) = delete;
diff --git a/libstdc++-v3/include/bits/unique_ptr.h b/libstdc++-v3/include/bits/unique_ptr.h
index 03f9bfc..56e6ec0 100644
--- a/libstdc++-v3/include/bits/unique_ptr.h
+++ b/libstdc++-v3/include/bits/unique_ptr.h
@@ -652,7 +652,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
   template
-inline
 typename enable_if::value>::type
 swap(unique_ptr<_Tp, _Dp>&,
 	 unique_ptr<_Tp, _Dp>&) = delete;
diff --git a/libstdc++-v3/include/debug/array b/libstdc++-v3/include/debug/array
index 48ab2fd..63e6808 100644
--- a/libstdc++-v3/include/debug/array
+++ b/libstdc++-v3/include/debug/array
@@ -260,6 +260,14 @@ namespace __debug
 { return !(__one < __two); }
 
   // Specialized algorithms.
+
+#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
+  template
+typename enable_if<
+  !_GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::_Is_swappable::value>::type
+swap(array<_Tp, _Nm>&, array<_Tp, _Nm>&) = delete;
+#endif
+
   template
 inline void
 swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two)
diff --git a/libstdc++-v3/include/std/array b/libstdc++-v3/include/std/array
index fa7bac6..f5028c9 100644
--- a/libstdc++-v3/include/std/array
+++ b/libstdc++-v3/include/std/array
@@ -290,7 +290,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
   template
-inline
 typename enable_if<
   !_GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::_Is_swappable::value>::type
 swap(array<_Tp, _Nm>&, array<_Tp, _Nm>&) = delete;
diff --git a/libstdc++-v3/include/std/optional b/libstdc++-v3/include/std/optional
index 191d64b..3d69e10 100644
--- a/libstdc++-v3/include/std/optional
+++ b/libstdc++-v3/include/std/optional
@@ -930,7 +930,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 { __lhs.swap(__rhs); }
 
   template
-inline enable_if_t && is_swappable_v<_Tp>)>
+

Re: [v3 PATCH] LWG 2766, LWG 2749

2016-11-30 Thread Jonathan Wakely

On 26/11/16 14:47 +0200, Ville Voutilainen wrote:

Updated patches attached, and tested with the full testsuite on Linux-PPC64.


Both patches are OK for trunk with the minor tweaks noted below.
Thanks.



diff --git a/libstdc++-v3/include/bits/stl_pair.h 
b/libstdc++-v3/include/bits/stl_pair.h
index ef52538..981dbeb 100644
--- a/libstdc++-v3/include/bits/stl_pair.h
+++ b/libstdc++-v3/include/bits/stl_pair.h
@@ -478,6 +478,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y)
noexcept(noexcept(__x.swap(__y)))
{ __x.swap(__y); }
+
+#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
+  template
+inline
+typename enable_if,
+  __is_swappable<_T2>>::value>::type
+swap(pair<_T1, _T2>&, pair<_T1, _T2>&) = delete;
+#endif
#endif // __cplusplus >= 201103L

  /**
diff --git a/libstdc++-v3/include/bits/unique_ptr.h 
b/libstdc++-v3/include/bits/unique_ptr.h
index f9ec60f..21b0bac 100644
--- a/libstdc++-v3/include/bits/unique_ptr.h
+++ b/libstdc++-v3/include/bits/unique_ptr.h
@@ -649,6 +649,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
swap(unique_ptr<_Tp, _Dp>& __x,
 unique_ptr<_Tp, _Dp>& __y) noexcept
{ __x.swap(__y); }


Insert a blank line here please.


+#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
+  template
+inline
+typename enable_if::value>::type
+swap(unique_ptr<_Tp, _Dp>&,
+unique_ptr<_Tp, _Dp>&) = delete;
+#endif

  template
diff --git a/libstdc++-v3/include/std/array b/libstdc++-v3/include/std/array
index 3ab0355..86100b5 100644
--- a/libstdc++-v3/include/std/array
+++ b/libstdc++-v3/include/std/array
@@ -287,6 +287,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two)
noexcept(noexcept(__one.swap(__two)))
{ __one.swap(__two); }


Insert a blank line here please.


+#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
+  template
+inline
+typename enable_if<
+  !_GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::_Is_swappable::value>::type
+swap(array<_Tp, _Nm>&, array<_Tp, _Nm>&) = delete;
+#endif

  template
constexpr _Tp&




diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index 63cacd4..8952750 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -1442,17 +1442,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
forward_as_tuple(_Elements&&... __args) noexcept
{ return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); }

-  template
-struct __is_tuple_like_impl> : true_type
-{ };
-
-  // Internal type trait that allows us to sfinae-protect tuple_cat.
-  template
-struct __is_tuple_like
-: public __is_tuple_like_impl::type>::type>::type
-{ };
-
  template
struct __make_tuple_impl;

@@ -1596,6 +1585,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y)
noexcept(noexcept(__x.swap(__y)))
{ __x.swap(__y); }


Insert a blank line here please.


+#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
+  template
+inline
+typename enable_if...>::value>::type
+swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete;
+#endif

  // A class (and instance) which can be used in 'tie' when an element
  // of a tuple is not required
diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index e5f2bba..49f76cc 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -2593,9 +2593,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  template 
struct __is_nothrow_swappable;

+  template
+class tuple;
+
+  template
+struct __is_tuple_like_impl : false_type
+{ };
+
+  template
+struct __is_tuple_like_impl> : true_type
+{ };
+
+  // Internal type trait that allows us to sfinae-protect tuple_cat.
+  template
+struct __is_tuple_like
+: public __is_tuple_like_impl::type>::type>::type


We can lose the std:: quals here.


+{ };
+
  template
inline
-typename enable_if<__and_,
+typename enable_if<__and_<__not_<__is_tuple_like<_Tp>>,
+ is_move_constructible<_Tp>,
  is_move_assignable<_Tp>>::value>::type
swap(_Tp&, _Tp&)
noexcept(__and_,


Re: [v3 PATCH] LWG 2766, LWG 2749

2016-11-26 Thread Ville Voutilainen
On 22 November 2016 at 17:06, Jonathan Wakely  wrote:
>> so I can certainly change all these swaps to use operator! rather than
>> __not_. Is the
>> patch otherwise ok for trunk? What about the tuple part?
>
>
> Yes, OK changing the top-level __not_s to operator!
> I haven't reviewed the tuple part fully yet.

Updated patches attached, and tested with the full testsuite on Linux-PPC64.
diff --git a/libstdc++-v3/include/bits/stl_pair.h 
b/libstdc++-v3/include/bits/stl_pair.h
index ef52538..981dbeb 100644
--- a/libstdc++-v3/include/bits/stl_pair.h
+++ b/libstdc++-v3/include/bits/stl_pair.h
@@ -478,6 +478,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y)
 noexcept(noexcept(__x.swap(__y)))
 { __x.swap(__y); }
+
+#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
+  template
+inline
+typename enable_if,
+  __is_swappable<_T2>>::value>::type
+swap(pair<_T1, _T2>&, pair<_T1, _T2>&) = delete;
+#endif
 #endif // __cplusplus >= 201103L
 
   /**
diff --git a/libstdc++-v3/include/bits/unique_ptr.h 
b/libstdc++-v3/include/bits/unique_ptr.h
index f9ec60f..21b0bac 100644
--- a/libstdc++-v3/include/bits/unique_ptr.h
+++ b/libstdc++-v3/include/bits/unique_ptr.h
@@ -649,6 +649,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 swap(unique_ptr<_Tp, _Dp>& __x,
 unique_ptr<_Tp, _Dp>& __y) noexcept
 { __x.swap(__y); }
+#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
+  template
+inline
+typename enable_if::value>::type
+swap(unique_ptr<_Tp, _Dp>&,
+unique_ptr<_Tp, _Dp>&) = delete;
+#endif
 
   template
diff --git a/libstdc++-v3/include/std/array b/libstdc++-v3/include/std/array
index 3ab0355..86100b5 100644
--- a/libstdc++-v3/include/std/array
+++ b/libstdc++-v3/include/std/array
@@ -287,6 +287,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two)
 noexcept(noexcept(__one.swap(__two)))
 { __one.swap(__two); }
+#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
+  template
+inline
+typename enable_if<
+  !_GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::_Is_swappable::value>::type
+swap(array<_Tp, _Nm>&, array<_Tp, _Nm>&) = delete;
+#endif
 
   template
 constexpr _Tp&
diff --git a/libstdc++-v3/include/std/optional 
b/libstdc++-v3/include/std/optional
index ea673cc..191d64b 100644
--- a/libstdc++-v3/include/std/optional
+++ b/libstdc++-v3/include/std/optional
@@ -930,6 +930,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 { __lhs.swap(__rhs); }
 
   template
+inline enable_if_t && is_swappable_v<_Tp>)>
+swap(optional<_Tp>&, optional<_Tp>&) = delete;
+
+  template
 constexpr optional>
 make_optional(_Tp&& __t)
 { return optional> { std::forward<_Tp>(__t) }; }
diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant
index 7d93575..c87d83d 100644
--- a/libstdc++-v3/include/std/variant
+++ b/libstdc++-v3/include/std/variant
@@ -877,10 +877,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   { return false; }
 
   template
-inline auto swap(variant<_Types...>& __lhs, variant<_Types...>& __rhs)
-noexcept(noexcept(__lhs.swap(__rhs))) -> decltype(__lhs.swap(__rhs))
+inline enable_if_t<__and_...,
+ is_swappable<_Types>...>::value>
+swap(variant<_Types...>& __lhs, variant<_Types...>& __rhs)
+noexcept(noexcept(__lhs.swap(__rhs)))
 { __lhs.swap(__rhs); }
 
+  template
+inline enable_if_t...,
+  is_swappable<_Types>...>::value>
+swap(variant<_Types...>&, variant<_Types...>&) = delete;
+
   class bad_variant_access : public exception
   {
   public:
diff --git a/libstdc++-v3/testsuite/20_util/optional/swap/2.cc 
b/libstdc++-v3/testsuite/20_util/optional/swap/2.cc
index 5793488..cb9291a 100644
--- a/libstdc++-v3/testsuite/20_util/optional/swap/2.cc
+++ b/libstdc++-v3/testsuite/20_util/optional/swap/2.cc
@@ -33,11 +33,11 @@ void swap(B&, B&) noexcept(false);
 static_assert( std::is_swappable_v );
 static_assert( !std::is_nothrow_swappable_v );
 
-// Not swappable, but optional is swappable via the generic std::swap.
+// Not swappable, and optional not swappable via the generic std::swap.
 struct C { };
 void swap(C&, C&) = delete;
 
-static_assert( std::is_swappable_v );
+static_assert( !std::is_swappable_v );
 
 // Not swappable, and optional not swappable via the generic std::swap.
 struct D { D(D&&) = delete; };
diff --git a/libstdc++-v3/testsuite/20_util/pair/swap_cxx17.cc 
b/libstdc++-v3/testsuite/20_util/pair/swap_cxx17.cc
new file mode 100644
index 000..6b09f42
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/pair/swap_cxx17.cc
@@ -0,0 +1,35 @@
+// { dg-options "-std=gnu++17" }
+// { dg-do compile }
+
+// Copyright (C) 2016 Free 

Re: [v3 PATCH] LWG 2766, LWG 2749

2016-11-22 Thread Jonathan Wakely

On 22/11/16 16:59 +0200, Ville Voutilainen wrote:

On 22 November 2016 at 15:36, Jonathan Wakely  wrote:

+#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or
gnu++11
+  template
+inline
+typename enable_if<__not_<__and_<__is_swappable<_T1>,
+__is_swappable<_T2>>>::value>::type
+swap(pair<_T1, _T2>&, pair<_T1, _T2>&) = delete;



Is there any advantage to using __not_ here, rather than just:

   typename enable_if,
  __is_swappable<_T2>>::value>::type

?

__not_ is useful as a sub-expression of an __and_ / __or_ expression,
but at the top level doesn't seem to buy anything, and is more typing,
and requires indenting the code further.



There's no particular advantage, it's just a habitual way to write a mixture of
__and_s and __not_s that I suffer from, whichever way the nesting is.
I'm also not consistent:

+inline enable_if_t && is_swappable_v<_Tp>)>
+swap(optional<_Tp>&, optional<_Tp>&) = delete;



Yes, I noticed that :-)


so I can certainly change all these swaps to use operator! rather than
__not_. Is the
patch otherwise ok for trunk? What about the tuple part?


Yes, OK changing the top-level __not_s to operator!

I haven't reviewed the tuple part fully yet.



Re: [v3 PATCH] LWG 2766, LWG 2749

2016-11-22 Thread Ville Voutilainen
On 22 November 2016 at 15:36, Jonathan Wakely  wrote:
>> +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or
>> gnu++11
>> +  template
>> +inline
>> +typename enable_if<__not_<__and_<__is_swappable<_T1>,
>> +__is_swappable<_T2>>>::value>::type
>> +swap(pair<_T1, _T2>&, pair<_T1, _T2>&) = delete;
>
>
> Is there any advantage to using __not_ here, rather than just:
>
>typename enable_if,
>   __is_swappable<_T2>>::value>::type
>
> ?
>
> __not_ is useful as a sub-expression of an __and_ / __or_ expression,
> but at the top level doesn't seem to buy anything, and is more typing,
> and requires indenting the code further.


There's no particular advantage, it's just a habitual way to write a mixture of
__and_s and __not_s that I suffer from, whichever way the nesting is.
I'm also not consistent:

+inline enable_if_t && is_swappable_v<_Tp>)>
+swap(optional<_Tp>&, optional<_Tp>&) = delete;

so I can certainly change all these swaps to use operator! rather than
__not_. Is the
patch otherwise ok for trunk? What about the tuple part?


Re: [v3 PATCH] LWG 2766, LWG 2749

2016-11-22 Thread Jonathan Wakely

On 17/11/16 23:38 +0200, Ville Voutilainen wrote:

@@ -478,6 +478,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y)
noexcept(noexcept(__x.swap(__y)))
{ __x.swap(__y); }
+
+#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
+  template
+inline
+typename enable_if<__not_<__and_<__is_swappable<_T1>,
+__is_swappable<_T2>>>::value>::type
+swap(pair<_T1, _T2>&, pair<_T1, _T2>&) = delete;


Is there any advantage to using __not_ here, rather than just:

   typename enable_if,
  __is_swappable<_T2>>::value>::type

?

__not_ is useful as a sub-expression of an __and_ / __or_ expression,
but at the top level doesn't seem to buy anything, and is more typing,
and requires indenting the code further.



Re: [v3 PATCH] LWG 2766, LWG 2749

2016-11-18 Thread Ville Voutilainen
On 18 November 2016 at 15:54, Jonathan Wakely  wrote:
> I agree, but if we'd just refused to support such undefined behaviour
> in stage 1 we wouldn't now be in a position of saying we can't change
> it in stage 3.

I want to support the code that the previous attempt breaks. I don't
think I can do so without
concepts.


Re: [v3 PATCH] LWG 2766, LWG 2749

2016-11-18 Thread Jonathan Wakely

On 17/11/16 23:38 +0200, Ville Voutilainen wrote:

The first patch does everything but the container adaptor parts (which
are wrong in the p/r) and the tuple part (which is icky). The second
part does the tuple parts, and needs some serious RFC. I know
it's ugly as sin, but it works. I don't think we should try to teach
our tuple to give the right answer for is_constructible etc., because
the last attempt at it broke boost and would break reasonable existing
code in addition to just boost - such things are not Stage 3 material,
imnsho.


I agree, but if we'd just refused to support such undefined behaviour
in stage 1 we wouldn't now be in a position of saying we can't change
it in stage 3.

Oh well, I'll review this ASAP.



[v3 PATCH] LWG 2766, LWG 2749

2016-11-17 Thread Ville Voutilainen
The first patch does everything but the container adaptor parts (which
are wrong in the p/r) and the tuple part (which is icky). The second
part does the tuple parts, and needs some serious RFC. I know
it's ugly as sin, but it works. I don't think we should try to teach
our tuple to give the right answer for is_constructible etc., because
the last attempt at it broke boost and would break reasonable existing
code in addition to just boost - such things are not Stage 3 material,
imnsho. We, imho, have two options: either skip the tuple parts
of LWG 2766 or tolerate the ugliness of that second patch. I can
tolerate that ugliness, it's not quite so hideous as I feared.

2016-11-18  Ville Voutilainen  

Implement LWG 2766,
Swapping non-swappable types and LWG 2749,
swappable traits for variants.
* include/bits/stl_pair.h (swap(pair<_T1, _T2>&, pair<_T1, _T2>&)):
Add a deleted overload.
* include/bits/unique_ptr.h
(swap(unique_ptr<_Tp, _Dp>&, unique_ptr<_Tp, _Dp>&)): Likewise.
* include/std/array
(swap(array<_Tp, _Nm>&, array<_Tp, _Nm>&)): Likewise.
* include/std/optional
(swap(optional<_Tp>&, optional<_Tp>&)): Likewise.
* include/std/variant
(swap(variant<_Types...>&, variant<_Types...>&)): Likewise.
* testsuite/20_util/optional/swap/2.cc: Add tests for disabled
swaps.
* testsuite/20_util/pair/swap_cxx17.cc: New.
* testsuite/20_util/unique_ptr/specialized_algorithms/swap_cxx17.cc:
Likewise.
* testsuite/20_util/variant/compile.cc: Add tests for disabled
swaps.
* testsuite/23_containers/array/specialized_algorithms/swap_cxx17.cc:
New.
* testsuite/23_containers/array/tuple_interface/get_neg.cc: Adjust.
* testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc:
Likewise.

2016-11-18  Ville Voutilainen  

Implement LWG 2766 for tuple.
* include/bits/move.h (swap(_Tp&, _Tp&)): Constrain
with __is_tuple_like.
* include/std/tuple (__is_tuple_like_impl, __is_tuple_like):
Move to type_traits.
(swap(tuple<_Elements...>&, tuple<_Elements...>&)): Add a deleted
overload.
* include/std/type_traits (__is_tuple_like_impl, __is_tuple_like):
New.
(swap(_Tp&, _Tp&)): Constrain with __is_tuple_like.
* include/std/utility (__is_tuple_like_impl): Move to type_traits.
* testsuite/20_util/tuple/swap_cxx17.cc: New.
diff --git a/libstdc++-v3/include/bits/stl_pair.h 
b/libstdc++-v3/include/bits/stl_pair.h
index ef52538..44568dd 100644
--- a/libstdc++-v3/include/bits/stl_pair.h
+++ b/libstdc++-v3/include/bits/stl_pair.h
@@ -478,6 +478,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y)
 noexcept(noexcept(__x.swap(__y)))
 { __x.swap(__y); }
+
+#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
+  template
+inline
+typename enable_if<__not_<__and_<__is_swappable<_T1>,
+__is_swappable<_T2>>>::value>::type
+swap(pair<_T1, _T2>&, pair<_T1, _T2>&) = delete;
+#endif
 #endif // __cplusplus >= 201103L
 
   /**
diff --git a/libstdc++-v3/include/bits/unique_ptr.h 
b/libstdc++-v3/include/bits/unique_ptr.h
index f9ec60f..c6bf4b6 100644
--- a/libstdc++-v3/include/bits/unique_ptr.h
+++ b/libstdc++-v3/include/bits/unique_ptr.h
@@ -649,6 +649,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 swap(unique_ptr<_Tp, _Dp>& __x,
 unique_ptr<_Tp, _Dp>& __y) noexcept
 { __x.swap(__y); }
+#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
+  template
+inline
+typename enable_if<__not_<__is_swappable<_Dp>>::value>::type
+swap(unique_ptr<_Tp, _Dp>&,
+unique_ptr<_Tp, _Dp>&) = delete;
+#endif
 
   template
diff --git a/libstdc++-v3/include/std/array b/libstdc++-v3/include/std/array
index 3ab0355..c43e281 100644
--- a/libstdc++-v3/include/std/array
+++ b/libstdc++-v3/include/std/array
@@ -287,6 +287,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two)
 noexcept(noexcept(__one.swap(__two)))
 { __one.swap(__two); }
+#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
+  template
+inline
+typename enable_if<__not_<
+  typename _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::_Is_swappable>
+  ::value>::type
+swap(array<_Tp, _Nm>&, array<_Tp, _Nm>&) = delete;
+#endif
 
   template
 constexpr _Tp&
diff --git a/libstdc++-v3/include/std/optional 
b/libstdc++-v3/include/std/optional
index ea673cc..191d64b 100644
--- a/libstdc++-v3/include/std/optional
+++ b/libstdc++-v3/include/std/optional
@@ -930,6 +930,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 { __lhs.swap(__rhs); }
 
   template
+inline enable_if_t && is_swappable_v<_Tp>)>
+swap(optional<_Tp>&, optional<_Tp>&) = delete;
+
+  template
 constexpr optional>
 make_optional(_Tp&& __t)
 { return