Re: [v3 PATCH, RFC] Implement LWG 2729 for tuple

2016-09-21 Thread Jonathan Wakely

On 31/08/16 19:49 +0300, Ville Voutilainen wrote:

@@ -338,6 +345,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  }
};

+  template
+struct __is_tuple_impl_trait_impl : false_type
+  { };
+
+  template
+struct __is_tuple_impl_trait_impl<_Tuple_impl<_Idx, _Tp...>> : true_type
+  { };
+
+  template
+struct __is_tuple_impl_trait : public __is_tuple_impl_trait_impl<_Tp>
+  { };


Please align the class bodies with the "struct" keyword here.

Otherwise OK for trunk, thanks.



Re: [v3 PATCH, RFC] Implement LWG 2729 for tuple

2016-08-31 Thread Ville Voutilainen
On 31 August 2016 at 18:40, Ville Voutilainen
 wrote:
> Now tested with the full testsuite on Linux-PPC64, test in the patch
> amended slightly.
> New patch attached.

I added some more torture to the new test and re-indented it.
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index c06a040..9f43732 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -220,8 +220,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   constexpr _Tuple_impl(const _Tuple_impl&) = default;
 
   constexpr
-  _Tuple_impl(_Tuple_impl&& __in)
-  noexcept(__and_,
+  _Tuple_impl(typename conditional<
+ __and_,
+is_move_constructible<_Inherited>>::value,
+ _Tuple_impl&&, __nonesuch&&>::type __in)
+   noexcept(__and_,
  is_nothrow_move_constructible<_Inherited>>::value)
   : _Inherited(std::move(_M_tail(__in))),
_Base(std::forward<_Head>(_M_head(__in))) { }
@@ -232,7 +235,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in)) { }
 
   template
-constexpr _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
+constexpr _Tuple_impl(typename conditional<
+ __and_,
+ is_move_constructible<_Inherited>>::value,
+ _Tuple_impl<_Idx, _UHead, _UTails...>&&,
+ __nonesuch&&>::type __in)
: _Inherited(std::move
 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
  _Base(std::forward<_UHead>
@@ -338,6 +345,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   }
 };
 
+  template
+struct __is_tuple_impl_trait_impl : false_type
+  { };
+
+  template
+struct __is_tuple_impl_trait_impl<_Tuple_impl<_Idx, _Tp...>> : true_type
+  { };
+
+  template
+struct __is_tuple_impl_trait : public __is_tuple_impl_trait_impl<_Tp>
+  { };
+
   // Basis case of inheritance recursion.
   template
 struct _Tuple_impl<_Idx, _Head>
@@ -356,11 +375,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   constexpr _Tuple_impl()
   : _Base() { }
 
+  template::value,
+ bool>::type=true>
   explicit
   constexpr _Tuple_impl(const _Head& __head)
   : _Base(__head) { }
 
-  template
+  template,
+__not_<__is_tuple_impl_trait<
+  typename
+remove_reference<_UHead>::type>>
+>::value,
+ bool>::type = true>
 explicit
 constexpr _Tuple_impl(_UHead&& __head)
: _Base(std::forward<_UHead>(__head)) { }
@@ -368,15 +396,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   constexpr _Tuple_impl(const _Tuple_impl&) = default;
 
   constexpr
-  _Tuple_impl(_Tuple_impl&& __in)
+  _Tuple_impl(typename conditional<
+ is_move_constructible<_Head>::value,
+ _Tuple_impl&&, __nonesuch&&>::type __in)
   noexcept(is_nothrow_move_constructible<_Head>::value)
   : _Base(std::forward<_Head>(_M_head(__in))) { }
 
-  template
+  template::value,
+ bool>::type = true>
 constexpr _Tuple_impl(const _Tuple_impl<_Idx, _UHead>& __in)
: _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in)) { }
 
-  template
+  template::value,
+ bool>::type = true>
 constexpr _Tuple_impl(_Tuple_impl<_Idx, _UHead>&& __in)
: _Base(std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
{ }
@@ -832,14 +866,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ }
 
   tuple&
-  operator=(const tuple& __in)
+  operator=(typename
+   conditional<__and_...>::value,
+   const tuple&, const __nonesuch&>::type __in)
   {
static_cast<_Inherited&>(*this) = __in;
return *this;
   }
 
   tuple&
-  operator=(tuple&& __in)
+  operator=(typename
+   conditional<__and_...>::value,
+   tuple&&, __nonesuch&&>::type __in)
   noexcept(is_nothrow_move_assignable<_Inherited>::value)
   {
static_cast<_Inherited&>(*this) = std::move(__in);
@@ -848,7 +886,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template::type>
+== sizeof...(_Elements)
+  &&
+  __and_...>::value>::type>
 tuple&
 operator=(const tuple<_UElements...>& __in)
 {
@@ -858,7 +899,10 @@ 

[v3 PATCH, RFC] Implement LWG 2729 for tuple

2016-08-30 Thread Ville Voutilainen
First, pardons all around if I'm completely repeating what Marc
already tried to do.
I think I'm taking a different approach.

I'm not adding any defaulted or deleted functions, so I don't think I'm changing
triviality. Chances are I need to actually delete the copy operations I want to
get rid of, though; currently they are defined with a conditional
parameter type.
That leaves open the possibility of a move operation being implicitly defaulted
rather than suppressed, which can make them trivial where they weren't before.

I'm not sure whether this has abi impact. In the sense that this is making
previously-defined move operations suppressed, maybe. I guess I could
alternatively try making them conditional, and making the inverse of the
conditional private; that should keep the traits working and retain abi
compatibility, because I don't think our toolchains at least on non-Windows
platforms include access levels in mangling.

Tested for tuple on Linux-x64. Thoughts?

2016-08-30  Ville Voutilainen  

Implement LWG 2729 for tuple.
* include/std/tuple (_Tuple_impl(_Tuple_impl&&)):
Suppress conditionally.
(_Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&&)): Likewise.
(__is_tuple_impl_trait_impl, __is_tuple_impl_trait): New.
(_Tuple_impl(const _Head&)): Constrain.
(_Tuple_impl(_UHead&&)): Likewise.
(_Tuple_impl(_Tuple_impl&&)): Suppress conditionally.
(_Tuple_impl(const _Tuple_impl<_Idx, _UHead>&)): Constrain.
(_Tuple_impl(_Tuple_impl<_Idx, _UHead>&&)): Likewise.
(operator=(const tuple&)): Enable conditionally.
(operator=(tuple&&)): Suppress conditionally.
(operator=(const tuple<_UElements...>&)): Constrain.
(operator=(tuple<_UElements...>&&)): Likewise.
(operator=(const tuple&)): Enable conditionally (2-param tuple).
(operator=(tuple&&)): Suppress conditionally (2-param tuple).
(operator=(const tuple<_U1, _U2>&)): Constrain.
(operator=(tuple<_U1, _U2>&&)): Likewise.
(operator=(const pair<_U1, _U2>&)): Likewise.
(operator=(pair<_U1, _U2>&&)): Likewise.
* testsuite/20_util/tuple/element_access/get_neg.cc: Adjust.
* testsuite/20_util/tuple/tuple_traits.cc: New.
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index c06a040..9f43732 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -220,8 +220,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   constexpr _Tuple_impl(const _Tuple_impl&) = default;
 
   constexpr
-  _Tuple_impl(_Tuple_impl&& __in)
-  noexcept(__and_,
+  _Tuple_impl(typename conditional<
+ __and_,
+is_move_constructible<_Inherited>>::value,
+ _Tuple_impl&&, __nonesuch&&>::type __in)
+   noexcept(__and_,
  is_nothrow_move_constructible<_Inherited>>::value)
   : _Inherited(std::move(_M_tail(__in))),
_Base(std::forward<_Head>(_M_head(__in))) { }
@@ -232,7 +235,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in)) { }
 
   template
-constexpr _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
+constexpr _Tuple_impl(typename conditional<
+ __and_,
+ is_move_constructible<_Inherited>>::value,
+ _Tuple_impl<_Idx, _UHead, _UTails...>&&,
+ __nonesuch&&>::type __in)
: _Inherited(std::move
 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
  _Base(std::forward<_UHead>
@@ -338,6 +345,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   }
 };
 
+  template
+struct __is_tuple_impl_trait_impl : false_type
+  { };
+
+  template
+struct __is_tuple_impl_trait_impl<_Tuple_impl<_Idx, _Tp...>> : true_type
+  { };
+
+  template
+struct __is_tuple_impl_trait : public __is_tuple_impl_trait_impl<_Tp>
+  { };
+
   // Basis case of inheritance recursion.
   template
 struct _Tuple_impl<_Idx, _Head>
@@ -356,11 +375,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   constexpr _Tuple_impl()
   : _Base() { }
 
+  template::value,
+ bool>::type=true>
   explicit
   constexpr _Tuple_impl(const _Head& __head)
   : _Base(__head) { }
 
-  template
+  template,
+__not_<__is_tuple_impl_trait<
+  typename
+remove_reference<_UHead>::type>>
+>::value,
+ bool>::type = true>
 explicit
 constexpr _Tuple_impl(_UHead&& __head)
: _Base(std::forward<_UHead>(__head)) { }
@@ -368,15 +396,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION