public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Adding noexcept-specification on tuple constructors (LWG 2899)
@ 2019-04-16 13:28 Nina Dinka Ranns
  2019-04-16 14:25 ` Jonathan Wakely
  0 siblings, 1 reply; 14+ messages in thread
From: Nina Dinka Ranns @ 2019-04-16 13:28 UTC (permalink / raw)
  To: gcc-patches, libstdc++

[-- Attachment #1: Type: text/plain, Size: 1226 bytes --]

Tested on Linux-PPC64
Adding noexcept-specification on tuple constructors (LWG 2899)


2019-04-13 Nina Dinka Ranns <dinka.ranns@gmail.com>

        Adding noexcept-specification on tuple constructors (LWG 2899)
        * libstdc++-v3/include/std/tuple:
        (tuple()): Add noexcept-specification.
        (tuple(const _Elements&...)): Likewise
        (tuple(_UElements&&...)): Likewise
        (tuple(const tuple<_UElements...>&)): Likewise
        (tuple(tuple<_UElements...>&&)): Likewise
        (tuple(const _T1&, const _T2&)): Likewise
        (tuple(_U1&&, _U2&&)): Likewise
        (tuple(const tuple<_U1, _U2>&): Likewise
        (tuple(tuple<_U1, _U2>&&): Likewise
        (tuple(const pair<_U1, _U2>&): Likewise
        (tuple(pair<_U1, _U2>&&): Likewise


        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc: New
        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs2.cc: New
        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs3.cc: New
        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs4.cc: New
        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs5.cc: New
        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs6.cc: New

[-- Attachment #2: noexcept_tuple.diff --]
[-- Type: application/octet-stream, Size: 63106 bytes --]

Index: libstdc++-v3/include/std/tuple
===================================================================
--- libstdc++-v3/include/std/tuple	(revision 268955)
+++ libstdc++-v3/include/std/tuple	(working copy)
@@ -552,6 +552,12 @@
 	  return
 	    __and_<is_nothrow_assignable<_Elements&, _UElements>...>::value;
 	}
+      template<typename... _UElements>
+	static constexpr bool __nothrow_constructible()
+	{
+	  return
+	    __and_<is_nothrow_constructible<_Elements, _UElements>...>::value;
+	}
 
     public:
       template<typename _Dummy = void,
@@ -559,6 +565,7 @@
                                     _ImplicitlyDefaultConstructibleTuple(),
                                   bool>::type = true>
       constexpr tuple()
+      noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
       : _Inherited() { }
 
       template<typename _Dummy = void,
@@ -569,6 +576,7 @@
                                     _ImplicitlyDefaultConstructibleTuple(),
                                   bool>::type = false>
       explicit constexpr tuple()
+      noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
       : _Inherited() { }
 
       // Shortcut for the cases where constructors taking _Elements...
@@ -586,6 +594,7 @@
                  && (sizeof...(_Elements) >= 1),
                bool>::type=true>
         constexpr tuple(const _Elements&... __elements)
+        noexcept(__nothrow_constructible<const _Elements&...>())
       : _Inherited(__elements...) { }
 
       template<typename _Dummy = void,
@@ -597,6 +606,7 @@
                  && (sizeof...(_Elements) >= 1),
                bool>::type=false>
       explicit constexpr tuple(const _Elements&... __elements)
+      noexcept(__nothrow_constructible<const _Elements&...>())
       : _Inherited(__elements...) { }
 
       // Shortcut for the cases where constructors taking _UElements...
@@ -624,6 +634,7 @@
                   && (sizeof...(_Elements) >= 1),
         bool>::type=true>
         constexpr tuple(_UElements&&... __elements)
+        noexcept(__and_<is_nothrow_constructible<_Elements,_UElements&&>...>::value)
         : _Inherited(std::forward<_UElements>(__elements)...) { }
 
       template<typename... _UElements, typename
@@ -635,6 +646,7 @@
                   && (sizeof...(_Elements) >= 1),
         bool>::type=false>
         explicit constexpr tuple(_UElements&&... __elements)
+        noexcept(__nothrow_constructible<_UElements&&...>())
 	: _Inherited(std::forward<_UElements>(__elements)...) {	}
 
       constexpr tuple(const tuple&) = default;
@@ -656,6 +668,7 @@
                     _NonNestedTuple<const tuple<_UElements...>&>(),
         bool>::type=true>
         constexpr tuple(const tuple<_UElements...>& __in)
+        noexcept(__nothrow_constructible<const _UElements&...>())
         : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
         { }
 
@@ -668,6 +681,7 @@
                     _NonNestedTuple<const tuple<_UElements...>&>(),
         bool>::type=false>
         explicit constexpr tuple(const tuple<_UElements...>& __in)
+        noexcept(__nothrow_constructible<const _UElements&...>())
         : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
         { }
 
@@ -680,6 +694,7 @@
                     _NonNestedTuple<tuple<_UElements...>&&>(),
         bool>::type=true>
         constexpr tuple(tuple<_UElements...>&& __in)
+        noexcept(__nothrow_constructible<_UElements&&...>())
         : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
 
       template<typename... _UElements, typename _Dummy = void, typename
@@ -691,6 +706,7 @@
                     _NonNestedTuple<tuple<_UElements...>&&>(),
         bool>::type=false>
         explicit constexpr tuple(tuple<_UElements...>&& __in)
+        noexcept(__nothrow_constructible<_UElements&&...>())
         : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
 
       // Allocator-extended constructors.
@@ -908,6 +924,13 @@
 			is_nothrow_assignable<_T2&, _U2>>::value;
 	}
 
+      template<typename _U1, typename _U2>
+    static constexpr bool __nothrow_constructible()
+    {
+      return __and_<is_nothrow_constructible<_T1, _U1>,
+    		is_nothrow_constructible<_T2, _U2>>::value;
+    }
+
     public:
       template <typename _U1 = _T1,
                 typename _U2 = _T2,
@@ -916,6 +939,8 @@
                                      __is_implicitly_default_constructible<_U2>>
                                    ::value, bool>::type = true>
 	constexpr tuple()
+	noexcept(__and_<is_nothrow_default_constructible<_T1>,
+   			is_nothrow_default_constructible<_T2>>::value)
 	: _Inherited() { }
 
       template <typename _U1 = _T1,
@@ -929,6 +954,8 @@
                              __is_implicitly_default_constructible<_U2>>>>
                   ::value, bool>::type = false>
 	explicit constexpr tuple()
+	noexcept(__and_<is_nothrow_default_constructible<_T1>,
+ 			is_nothrow_default_constructible<_T2>>::value)
 	: _Inherited() { }
 
       // Shortcut for the cases where constructors taking _T1, _T2
@@ -943,6 +970,7 @@
                            _ImplicitlyConvertibleTuple<_T1, _T2>(),
 	bool>::type = true>
         constexpr tuple(const _T1& __a1, const _T2& __a2)
+        noexcept(__nothrow_constructible<const _T1&, const _T2&>())
         : _Inherited(__a1, __a2) { }
 
       template<typename _Dummy = void, typename
@@ -952,6 +980,7 @@
                            _ImplicitlyConvertibleTuple<_T1, _T2>(),
 	bool>::type = false>
         explicit constexpr tuple(const _T1& __a1, const _T2& __a2)
+        noexcept(__nothrow_constructible<const _T1&, const _T2&>())
         : _Inherited(__a1, __a2) { }
 
       // Shortcut for the cases where constructors taking _U1, _U2
@@ -966,6 +995,7 @@
 	          && !is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value,
 	bool>::type = true>
         constexpr tuple(_U1&& __a1, _U2&& __a2)
+        noexcept(__nothrow_constructible<_U1&&,_U2&&>())
 	: _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
 
       template<typename _U1, typename _U2, typename
@@ -976,6 +1006,7 @@
 	          && !is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value,
 	bool>::type = false>
         explicit constexpr tuple(_U1&& __a1, _U2&& __a2)
+        noexcept(__nothrow_constructible<_U1&&,_U2&&>())
 	: _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
 
       constexpr tuple(const tuple&) = default;
@@ -989,6 +1020,7 @@
                     _ImplicitlyConvertibleTuple<_U1, _U2>(),
 	bool>::type = true>
         constexpr tuple(const tuple<_U1, _U2>& __in)
+        noexcept(__nothrow_constructible<const _U1&,const _U2&>())
 	: _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
 
       template<typename _U1, typename _U2, typename
@@ -998,6 +1030,7 @@
                     _ImplicitlyConvertibleTuple<_U1, _U2>(),
 	bool>::type = false>
         explicit constexpr tuple(const tuple<_U1, _U2>& __in)
+        noexcept(__nothrow_constructible<const _U1&,const _U2&>())
 	: _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
 
       template<typename _U1, typename _U2, typename
@@ -1007,6 +1040,7 @@
                     _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
 	bool>::type = true>
         constexpr tuple(tuple<_U1, _U2>&& __in)
+        noexcept(__nothrow_constructible<_U1&&,_U2&&>())
 	: _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
 
       template<typename _U1, typename _U2, typename
@@ -1016,6 +1050,7 @@
                     _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
 	bool>::type = false>
         explicit constexpr tuple(tuple<_U1, _U2>&& __in)
+        noexcept(__nothrow_constructible<_U1&&,_U2&&>())
 	: _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
 
       template<typename _U1, typename _U2, typename
@@ -1025,6 +1060,7 @@
                     _ImplicitlyConvertibleTuple<_U1, _U2>(),
 	bool>::type = true>
         constexpr tuple(const pair<_U1, _U2>& __in)
+        noexcept(__nothrow_constructible<const _U1&,const _U2&>())
 	: _Inherited(__in.first, __in.second) { }
 
       template<typename _U1, typename _U2, typename
@@ -1034,6 +1070,7 @@
                     _ImplicitlyConvertibleTuple<_U1, _U2>(),
 	bool>::type = false>
         explicit constexpr tuple(const pair<_U1, _U2>& __in)
+        noexcept(__nothrow_constructible<const _U1&,const _U2&>())
 	: _Inherited(__in.first, __in.second) { }
 
       template<typename _U1, typename _U2, typename
@@ -1043,6 +1080,7 @@
                     _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
 	bool>::type = true>
         constexpr tuple(pair<_U1, _U2>&& __in)
+        noexcept(__nothrow_constructible<_U1&&,_U2&&>())
 	: _Inherited(std::forward<_U1>(__in.first),
 		     std::forward<_U2>(__in.second)) { }
 
@@ -1053,6 +1091,7 @@
                     _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
 	bool>::type = false>
         explicit constexpr tuple(pair<_U1, _U2>&& __in)
+        noexcept(__nothrow_constructible<_U1&&,_U2&&>())
 	: _Inherited(std::forward<_U1>(__in.first),
 		     std::forward<_U2>(__in.second)) { }
 
Index: libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc
===================================================================
--- libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc	(nonexistent)
+++ libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc	(working copy)
@@ -0,0 +1,191 @@
+// { dg-options { -std=gnu++2a } }
+// { dg-do run { target c++2a } }
+
+// 2019-04-10  Nina Dinka Ranns  <dinka.ranns@gmail.com>
+//
+// Copyright (C) 2017 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>
+#include <testsuite_tr1.h>
+#include <utility>
+
+/* DefaultConstructionTests */
+
+using namespace __gnu_test;
+
+bool throwing_ctor_called = false;
+
+
+template<typename T>
+bool  checkDefaultThrowConstruct()
+{
+  throwing_ctor_called = false;
+  bool deduced_nothrow = std::is_nothrow_constructible<T>::value;
+  T t{};
+  return throwing_ctor_called != deduced_nothrow;
+}
+
+
+typedef std::tuple<int> IT;
+typedef std::tuple<const int> CIT;
+typedef std::tuple<int&&> RVIT;
+typedef std::tuple<int, int> IIT;
+typedef std::pair<int, int> IIP;
+typedef std::tuple<int, int, int> IIIT;
+
+namespace DefaultConstructionTests
+{
+  struct NoexceptDC
+  {
+    NoexceptDC() noexcept(true){}
+  };
+
+  struct ExceptDC
+  {
+    ExceptDC() noexcept(false)
+      {  throwing_ctor_called = true; }
+  };
+
+  struct ExplicitNoexceptDC
+  {
+    explicit ExplicitNoexceptDC() noexcept(true)
+        {}
+  };
+
+  struct ExplicitExceptDC
+  {
+    explicit ExplicitExceptDC() noexcept(false)
+        {  throwing_ctor_called = true; }
+  };
+
+  typedef std::tuple<NoexceptDC> NDT;
+  typedef std::tuple<ExceptDC> EDT;
+  typedef std::tuple<ExplicitNoexceptDC> X_NDT;
+  typedef std::tuple<ExplicitExceptDC> X_EDT;
+
+  typedef std::tuple<NoexceptDC,NoexceptDC> NNDT;
+  typedef std::tuple<ExceptDC,ExceptDC> EEDT;
+  typedef std::tuple<ExceptDC,NoexceptDC> ENDT;
+  typedef std::tuple<ExplicitNoexceptDC,NoexceptDC> X_NNDT;
+  typedef std::tuple<ExplicitExceptDC,ExceptDC> X_EEDT;
+  typedef std::tuple<ExceptDC,ExplicitNoexceptDC> X_ENDT;
+
+  typedef std::tuple<long, NoexceptDC, NoexceptDC> LNDNDT;
+  typedef std::tuple<long, NoexceptDC, ExceptDC> LNDEDT;
+  typedef std::tuple<long, ExplicitNoexceptDC, NoexceptDC> X_LNEDNDT;
+  typedef std::tuple<long, ExplicitNoexceptDC, ExceptDC> X_LNEDEDT;
+  typedef std::tuple<long, ExplicitExceptDC, ExceptDC> X_LEEDEDT;
+
+
+  /* if it has E in the name, it contains a type that throws when default constructed */
+  static_assert(std::is_nothrow_constructible<IT>::value, "");
+  static_assert(std::is_nothrow_constructible<NDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<EDT>::value, "");
+  static_assert(std::is_nothrow_constructible<X_NDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<X_EDT>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IIT>::value, "");
+  static_assert(std::is_nothrow_constructible<NNDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<EEDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<ENDT>::value, "");
+  static_assert(std::is_nothrow_constructible<X_NNDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<X_EEDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<X_ENDT>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IIIT>::value, "");
+  static_assert(std::is_nothrow_constructible<LNDNDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<LNDEDT>::value, "");
+  static_assert(std::is_nothrow_constructible<X_LNEDNDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<X_LNEDEDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<X_LEEDEDT>::value, "");
+
+  void Run()
+  {
+    VERIFY( checkDefaultThrowConstruct<IT>() );
+    VERIFY( checkDefaultThrowConstruct<NDT>() );
+    VERIFY( checkDefaultThrowConstruct<EDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_NDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_EDT>() );
+
+    VERIFY( checkDefaultThrowConstruct<IIT>() );
+    VERIFY( checkDefaultThrowConstruct<NNDT>() );
+    VERIFY( checkDefaultThrowConstruct<EEDT>() );
+    VERIFY( checkDefaultThrowConstruct<ENDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_NNDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_EEDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_ENDT>() );
+
+    VERIFY( checkDefaultThrowConstruct<IIIT>() );
+    VERIFY( checkDefaultThrowConstruct<LNDNDT>() );
+    VERIFY( checkDefaultThrowConstruct<LNDEDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_LNEDNDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_LNEDEDT>() );
+  }
+}
+
+
+int main()
+{
+
+  DefaultConstructionTests::Run();
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs2.cc
===================================================================
--- libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs2.cc	(nonexistent)
+++ libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs2.cc	(working copy)
@@ -0,0 +1,129 @@
+// { dg-options { -std=gnu++2a } }
+// { dg-do run { target c++2a } }
+
+// 2019-04-10  Nina Dinka Ranns  <dinka.ranns@gmail.com>
+//
+// Copyright (C) 2017 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>
+#include <testsuite_tr1.h>
+#include <utility>
+
+using namespace __gnu_test;
+
+/* AllNoThrowTests */
+
+typedef std::tuple<int> IT;
+typedef std::tuple<const int> CIT;
+typedef std::tuple<int&&> RVIT;
+typedef std::tuple<int, int> IIT;
+typedef std::pair<int, int> IIP;
+typedef std::tuple<int, int, int> IIIT;
+
+namespace AllNoThrow
+{
+  static_assert(std::is_nothrow_constructible<IT, int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IT, const int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IT, int&&>::value, "");
+  static_assert(std::is_nothrow_constructible<IT, const int&&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IT, IT>::value, "");
+  static_assert(std::is_nothrow_constructible<IT, const IT &>::value, "");
+  static_assert(std::is_nothrow_constructible<IT, CIT>::value, "");
+
+  static_assert(std::is_nothrow_convertible<int&, IT>::value, "");
+  static_assert(std::is_nothrow_convertible<const int&, IT>::value, "");
+  static_assert(std::is_nothrow_convertible<int&&, IT>::value, "");
+  static_assert(std::is_nothrow_convertible<const int&&, IT>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IIT, int&, int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIT, const int&, const int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIT, int&&, int&&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIT, const int&&, const int&&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IIT, IIT>::value, "");
+  static_assert(std::is_nothrow_constructible<IIT, const IIT &>::value, "");
+  static_assert(std::is_nothrow_constructible<IIT, IIP>::value, "");
+  static_assert(std::is_nothrow_constructible<IIT, const IIP>::value, "");
+
+  static_assert(std::is_nothrow_convertible<IIT, IIT>::value, "");
+  static_assert(std::is_nothrow_convertible<const IIT &, IIT>::value, "");
+  static_assert(std::is_nothrow_convertible<IIP, IIT>::value, "");
+  static_assert(std::is_nothrow_convertible<const IIP, IIT>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IIIT, IIIT&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIIT, const IIIT &>::value, "");
+  static_assert(std::is_nothrow_constructible<IIIT, IIIT&&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIIT, const IIIT&&>::value, "");
+
+  static_assert(std::is_nothrow_convertible<IIIT&, IIIT>::value, "");
+  static_assert(std::is_nothrow_convertible<const IIIT &, IIIT>::value, "");
+  static_assert(std::is_nothrow_convertible<IIIT&&, IIIT>::value, "");
+  static_assert(std::is_nothrow_convertible<const IIIT&&, IIIT>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IIIT, int&, int&, int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIIT, const int&, const int&, int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIIT, int&&, int&&, int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIIT, const int&&, const int&&, int&>::value, "");
+}
+
+int main()
+{
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs3.cc
===================================================================
--- libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs3.cc	(nonexistent)
+++ libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs3.cc	(working copy)
@@ -0,0 +1,307 @@
+// { dg-options { -std=gnu++2a } }
+// { dg-do run { target c++2a } }
+
+// 2019-04-10  Nina Dinka Ranns  <dinka.ranns@gmail.com>
+//
+// Copyright (C) 2017 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/>.
+
+/* throw copy,no throw conversion */
+
+#include <tuple>
+#include <testsuite_tr1.h>
+#include <utility>
+
+using namespace __gnu_test;
+
+bool throwing_ctor_called = false;
+
+template<typename T,typename U>
+bool  checkCopyThrowConstruct()
+{
+  throwing_ctor_called = false;
+  bool deduced_nothrow = std::is_nothrow_constructible<T,U&>::value;
+  U u;
+  T t{u};
+
+  return throwing_ctor_called != deduced_nothrow;
+}
+template<typename T,typename U>
+bool  checkMoveThrowConstruct()
+{
+  throwing_ctor_called = false;
+  bool deduced_nothrow = std::is_nothrow_constructible<T,U&&>::value;
+  U u;
+  T t{std::move(u)};
+  return throwing_ctor_called != deduced_nothrow;
+}
+
+
+typedef std::tuple<int> IT;
+typedef std::tuple<const int> CIT;
+typedef std::tuple<int&&> RVIT;
+typedef std::tuple<int,int> IIT;
+typedef std::pair<int,int> IIP;
+typedef std::tuple<int,int,int> IIIT;
+
+namespace ThrowCopyNothrowConversion
+{
+  struct A
+  {
+    A() noexcept(true)
+        {}
+
+    A(const int&) noexcept(true)
+      {}
+
+    A(const A&) noexcept(false)
+      {  throwing_ctor_called = true; }
+
+  };
+
+  typedef std::tuple<A> AT;
+  typedef std::tuple<A,A> AAT;
+  typedef std::pair<A,A> AAP;
+  typedef std::tuple<int,A> IAT;
+  typedef std::pair<int,A> IAP;
+  typedef std::tuple<A,A,A> AAAT;
+  typedef std::tuple<int,int,A> IIAT;
+
+/* one element tests */
+  static_assert(std::is_nothrow_constructible<AT,int>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,const int>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,int&>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,const int &>::value,"");
+
+  static_assert(std::is_nothrow_constructible<AT,IT>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,const IT>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,IT&>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,const IT &>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,std::tuple<int&>>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,const std::tuple<int&&>>::value,"");
+
+  static_assert(std::is_nothrow_convertible<int,AT>::value,"");
+  static_assert(std::is_nothrow_convertible<const int,AT>::value,"");
+  static_assert(std::is_nothrow_convertible<int&,AT>::value,"");
+  static_assert(std::is_nothrow_convertible<const int &,AT>::value,"");
+
+  static_assert(std::is_nothrow_convertible<IT,AT>::value,"");
+  static_assert(std::is_nothrow_convertible<const IT,AT>::value,"");
+  static_assert(std::is_nothrow_convertible<IT&,AT>::value,"");
+  static_assert(std::is_nothrow_convertible<const IT &,AT>::value,"");
+  static_assert(std::is_nothrow_convertible<std::tuple<int&>,AT>::value,"");
+  static_assert(std::is_nothrow_convertible<const std::tuple<int&&>,AT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<AT,A>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,const A>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,A&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,const A &>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<AT,AT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,const AT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,AT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,const AT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,std::tuple<A&>>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,const std::tuple<A&&>>::value,"");
+
+  static_assert(!std::is_nothrow_convertible<A,AT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const A,AT>::value,"");
+  static_assert(!std::is_nothrow_convertible<A&,AT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const A &,AT>::value,"");
+
+  static_assert(!std::is_nothrow_convertible<AT,AT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const AT,AT>::value,"");
+  static_assert(!std::is_nothrow_convertible<AT&,AT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const AT &,AT>::value,"");
+  static_assert(!std::is_nothrow_convertible<std::tuple<A&>,AT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const std::tuple<A&&>,AT>::value,"");
+
+/* two element tests */
+
+  static_assert(std::is_nothrow_constructible<AAT,IIT>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,const IIT>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,IIT&>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,const IIT &>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,IIP>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,const IIP>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,IIP&>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,const IIP &>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,std::tuple<int&,int&>>::value,"");
+
+  static_assert(std::is_nothrow_convertible<IIT,AAT>::value,"");
+  static_assert(std::is_nothrow_convertible<const IIT,AAT>::value,"");
+  static_assert(std::is_nothrow_convertible<IIT&,AAT>::value,"");
+  static_assert(std::is_nothrow_convertible<const IIT &,AAT>::value,"");
+  static_assert(std::is_nothrow_convertible<IIP,AAT>::value,"");
+  static_assert(std::is_nothrow_convertible<const IIP,AAT>::value,"");
+  static_assert(std::is_nothrow_convertible<IIP&,AAT>::value,"");
+  static_assert(std::is_nothrow_convertible<const IIP &,AAT>::value,"");
+  static_assert(std::is_nothrow_convertible<std::tuple<int&,int&>,AAT>::value,"");
+
+
+  static_assert(!std::is_nothrow_constructible<AAT,AAT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const AAT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,AAT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const AAT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,AAP>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const AAP>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,AAP&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const AAP &>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,std::tuple<A&,A&>>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<AAT,IAT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const IAT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,IAT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const IAT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,IAP>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const IAP>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,IAP&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const IAP &>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,std::tuple<A&,int&>>::value,"");
+
+  static_assert(!std::is_nothrow_convertible<AAT,AAT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const AAT,AAT>::value,"");
+  static_assert(!std::is_nothrow_convertible<AAT&,AAT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const AAT &,AAT>::value,"");
+  static_assert(!std::is_nothrow_convertible<AAP,AAT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const AAP,AAT>::value,"");
+  static_assert(!std::is_nothrow_convertible<AAP&,AAT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const AAP &,AAT>::value,"");
+  static_assert(!std::is_nothrow_convertible<std::tuple<A&,A&>,AAT>::value,"");
+
+  static_assert(!std::is_nothrow_convertible<IAT,AAT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const IAT,AAT>::value,"");
+  static_assert(!std::is_nothrow_convertible<IAT&,AAT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const IAT &,AAT>::value,"");
+  static_assert(!std::is_nothrow_convertible<IAP,AAT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const IAP,AAT>::value,"");
+  static_assert(!std::is_nothrow_convertible<IAP&,AAT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const IAP &,AAT>::value,"");
+  static_assert(!std::is_nothrow_convertible<std::tuple<A&,int&>,AAT>::value,"");
+
+
+  static_assert(std::is_nothrow_constructible<AAT,int&,const int&>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,int&&,const int&&>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<AAT,A&,const A&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,A&&,const A&&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const A &&,const int&&>::value,"");
+
+/* three element tests */
+  static_assert(std::is_nothrow_constructible<AAAT,IIIT>::value,"");
+  static_assert(std::is_nothrow_constructible<AAAT,const IIIT>::value,"");
+  static_assert(std::is_nothrow_constructible<AAAT,IIIT&>::value,"");
+  static_assert(std::is_nothrow_constructible<AAAT,const IIIT &>::value,"");
+
+  static_assert(std::is_nothrow_convertible<IIIT,AAAT>::value,"");
+  static_assert(std::is_nothrow_convertible<const IIIT,AAAT>::value,"");
+  static_assert(std::is_nothrow_convertible<IIIT&,AAAT>::value,"");
+  static_assert(std::is_nothrow_convertible<const IIIT &,AAAT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<AAAT,IIAT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAAT,const IIAT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAAT,IIAT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAAT,const IIAT &>::value,"");
+
+  static_assert(!std::is_nothrow_convertible<IIAT,AAAT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const IIAT,AAAT>::value,"");
+  static_assert(!std::is_nothrow_convertible<IIAT&,AAAT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const IIAT &,AAAT>::value,"");
+
+  static_assert(std::is_nothrow_constructible<AAAT,int&,const int&,int&&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAAT,int &,const A &&,const int&&>::value,"");
+
+  void Run()
+  {
+    VERIFY( (checkCopyThrowConstruct<AT,int>()) );
+    VERIFY( (checkMoveThrowConstruct<AT,int>()) );
+    VERIFY( (checkCopyThrowConstruct<AT,A>()) );
+    VERIFY( (checkMoveThrowConstruct<AT,A>()) );
+    VERIFY( (checkCopyThrowConstruct<AT,AT>()) );
+    VERIFY( (checkMoveThrowConstruct<AT,AT>()) );
+    VERIFY( (checkCopyThrowConstruct<AT,IT>()) );
+    VERIFY( (checkMoveThrowConstruct<AT,IT>()) );
+    VERIFY( (checkMoveThrowConstruct<AT,CIT>()) );
+    VERIFY( (checkCopyThrowConstruct<AAT,AAT>()) );
+    VERIFY( (checkMoveThrowConstruct<AAT,AAT>()) );
+    VERIFY( (checkCopyThrowConstruct<AAT,IIT>()) );
+    VERIFY( (checkMoveThrowConstruct<AAT,IIT>()) );
+    VERIFY( (checkCopyThrowConstruct<AAT,IIP>()) );
+    VERIFY( (checkMoveThrowConstruct<AAT,IIP>()) );
+
+    VERIFY( (checkCopyThrowConstruct<AAT,std::tuple<int,A>>()) );
+    VERIFY( (checkMoveThrowConstruct<AAT,std::tuple<int,A>>()) );
+    VERIFY( (checkCopyThrowConstruct<AAT,std::pair<int,A>>()) );
+    VERIFY( (checkMoveThrowConstruct<AAT,std::pair<int,A>>()) );
+
+    VERIFY( (checkCopyThrowConstruct<AAAT,AAAT>()) );
+    VERIFY( (checkMoveThrowConstruct<AAAT,AAAT>()) );
+    VERIFY( (checkCopyThrowConstruct<AAAT,IIAT>()) );
+    VERIFY( (checkMoveThrowConstruct<AAAT,IIAT>()) );
+  }
+}
+
+int main()
+{
+
+  ThrowCopyNothrowConversion::Run();
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs4.cc
===================================================================
--- libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs4.cc	(nonexistent)
+++ libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs4.cc	(working copy)
@@ -0,0 +1,481 @@
+// { dg-options { -std=gnu++2a } }
+// { dg-do run { target c++17 } }
+
+// 2019-04-10  Nina Dinka Ranns  <dinka.ranns@gmail.com>
+//
+// Copyright (C) 2017 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>
+#include <testsuite_tr1.h>
+#include <utility>
+
+using namespace __gnu_test;
+
+// Nothrow Copy
+// Throw Move
+// Throw CopyConversion
+// Nothrow MoveConversion
+
+bool throwing_ctor_called = false;
+
+template<typename T, typename U>
+bool  checkCopyThrowConstruct()
+{
+  throwing_ctor_called = false;
+  bool deduced_nothrow = std::is_nothrow_constructible<T, U&>::value;
+  U u;
+  T t{u};
+  return throwing_ctor_called != deduced_nothrow;
+}
+template<typename T, typename U>
+bool  checkMoveThrowConstruct()
+{
+  throwing_ctor_called = false;
+  bool deduced_nothrow = std::is_nothrow_constructible<T, U&&>::value;
+  U u;
+  T t{std::move(u)};
+  return throwing_ctor_called != deduced_nothrow;
+}
+
+
+typedef std::tuple<int> IT;
+typedef std::tuple<const int> CIT;
+typedef std::tuple<int&&> RVIT;
+typedef std::tuple<int, int> IIT;
+typedef std::pair<int, int> IIP;
+typedef std::tuple<int, int, int> IIIT;
+
+namespace NothrowCopyThrowMoveThrowCopyConversionNothrowMoveConversion
+{
+  struct B
+  {
+    B() noexcept(true)
+        {}
+
+    B(const int&) noexcept(false)
+      {  throwing_ctor_called = true; }
+
+    B(int&&) noexcept(true)
+      {}
+
+    B(const B&) noexcept(true)
+      {}
+
+    B(B&&) noexcept(false)
+      {  throwing_ctor_called = true; }
+  };
+
+
+  struct D
+  {
+    D() noexcept(true)
+        {}
+
+    explicit
+    D(const int&) noexcept(false)
+    {  throwing_ctor_called = true; }
+
+    explicit
+    D(int&&) noexcept(true)
+        {}
+
+    explicit
+    D(const D&) noexcept(true)
+      {}
+
+    explicit
+    D(D&&) noexcept(false)
+    {  throwing_ctor_called = true; }
+
+  };
+
+  typedef std::tuple<B> BT;
+  typedef std::tuple<B,B> BBT;
+  typedef std::pair<B,B> BBP;
+  typedef std::tuple<D> DT;
+  typedef std::tuple<D,D> DDT;
+  typedef std::pair<D,D> DDP;
+  typedef std::tuple<int,D> IDT;
+  typedef std::pair<int,D> IDP;
+  typedef std::tuple<int,B> IBT;
+  typedef std::pair<int,B> IBP;
+  typedef std::tuple<D,B> DBT;
+  typedef std::pair<D,B> DBP;
+  typedef std::tuple<B,B,B> BBBT;
+  typedef std::tuple<D,D,D> DDDT;
+  typedef std::tuple<int,D,int> IDIT;
+  typedef std::tuple<int,B,int> IBIT;
+  typedef std::tuple<int,D,B> IDBT;
+
+/* one element tests */
+  static_assert(std::is_nothrow_constructible<BT, int>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, const int>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, int&>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, const int &>::value, "");
+
+  static_assert(std::is_nothrow_constructible<BT, IT>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT,const IT>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, IT&>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, const IT &>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, std::tuple<int&>>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, const std::tuple<int&&>>::value, "");
+
+  static_assert(std::is_nothrow_convertible<int,BT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const int,BT>::value,"");
+  static_assert(!std::is_nothrow_convertible<int&,BT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const int &,BT>::value,"");
+
+  static_assert(std::is_nothrow_convertible<IT,BT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const IT,BT>::value,"");
+  static_assert(!std::is_nothrow_convertible<IT&,BT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const IT &,BT>::value,"");
+  static_assert(!std::is_nothrow_convertible<std::tuple<int&>,BT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const std::tuple<int&&>,BT>::value,"");
+
+
+  static_assert(!std::is_nothrow_constructible<BT, B>::value, "");
+  static_assert(std::is_nothrow_constructible<BT,const B>::value, "");
+  static_assert(std::is_nothrow_constructible<BT, B&>::value, "");
+  static_assert(std::is_nothrow_constructible<BT, const B &>::value, "");
+
+  static_assert(!std::is_nothrow_constructible<BT, BT>::value, "");
+  static_assert(std::is_nothrow_constructible<BT,const BT>::value, "");
+  static_assert(std::is_nothrow_constructible<BT, BT&>::value, "");
+  static_assert(std::is_nothrow_constructible<BT, const BT &>::value, "");
+  static_assert(std::is_nothrow_constructible<BT, std::tuple<B&>>::value, "");
+  static_assert(std::is_nothrow_constructible<BT, const std::tuple<B&&>>::value, "");
+
+  static_assert(!std::is_nothrow_convertible<B,BT>::value,"");
+  static_assert(std::is_nothrow_convertible<const B,BT>::value,"");
+  static_assert(std::is_nothrow_convertible<B&,BT>::value,"");
+  static_assert(std::is_nothrow_convertible<const B &,BT>::value,"");
+
+  static_assert(!std::is_nothrow_convertible<BT,BT>::value,"");
+  static_assert(std::is_nothrow_convertible<const BT,BT>::value,"");
+  static_assert(std::is_nothrow_convertible<BT&,BT>::value,"");
+  static_assert(std::is_nothrow_convertible<const BT &,BT>::value,"");
+  static_assert(std::is_nothrow_convertible<std::tuple<B&>,BT>::value,"");
+  static_assert(std::is_nothrow_convertible<const std::tuple<B&&>,BT>::value,"");
+
+/* explicit */
+  static_assert(std::is_nothrow_constructible<DT, int>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, const int>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, int&>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, const int &>::value, "");
+
+  static_assert(std::is_nothrow_constructible<DT, IT>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT,const IT>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, IT&>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, const IT &>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, std::tuple<int&>>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, const std::tuple<int&&>>::value, "");
+
+  static_assert(!std::is_nothrow_constructible<DT, D>::value, "");
+  static_assert(std::is_nothrow_constructible<DT,const D>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, D&>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const D &>::value, "");
+
+  static_assert(!std::is_nothrow_constructible<DT, DT>::value, "");
+  static_assert(std::is_nothrow_constructible<DT,const DT>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, DT&>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const DT &>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, std::tuple<D&>>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const std::tuple<D&&>>::value, "");
+
+  static_assert(!std::is_nothrow_convertible<DT,DT>::value,"");
+  static_assert(std::is_nothrow_convertible<const DT,DT>::value,"");
+  static_assert(std::is_nothrow_convertible<DT&,DT>::value,"");
+  static_assert(std::is_nothrow_convertible<const DT &,DT>::value,"");
+
+/* two elements tests */
+  static_assert(std::is_nothrow_constructible<BBT,IIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,IIT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IIT &>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,IIP>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IIP>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,IIP&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IIP &>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,std::tuple<int&,int&>>::value,"");
+
+  static_assert(std::is_nothrow_convertible<IIT,BBT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const IIT,BBT>::value,"");
+  static_assert(!std::is_nothrow_convertible<IIT&,BBT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const IIT &,BBT>::value,"");
+  static_assert(std::is_nothrow_convertible<IIP,BBT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const IIP,BBT>::value,"");
+  static_assert(!std::is_nothrow_convertible<IIP&,BBT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const IIP &,BBT>::value,"");
+  static_assert(!std::is_nothrow_convertible<std::tuple<int&,int&>,BBT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<BBT,BBT>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,const BBT>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,BBT&>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,const BBT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,BBP>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,const BBP>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,BBP&>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,const BBP &>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,std::tuple<B&,B&>>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<BBT,IBT>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IBT>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,IBT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IBT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,IBP>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IBP>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,IBP&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IBP &>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,std::tuple<const B&,int&&>>::value,"");
+
+  static_assert(!std::is_nothrow_convertible<BBT,BBT>::value,"");
+  static_assert(std::is_nothrow_convertible<const BBT,BBT>::value,"");
+  static_assert(std::is_nothrow_convertible<BBT&,BBT>::value,"");
+  static_assert(std::is_nothrow_convertible<const BBT &,BBT>::value,"");
+  static_assert(!std::is_nothrow_convertible<BBP,BBT>::value,"");
+  static_assert(std::is_nothrow_convertible<const BBP,BBT>::value,"");
+  static_assert(std::is_nothrow_convertible<BBP&,BBT>::value,"");
+  static_assert(std::is_nothrow_convertible<const BBP &,BBT>::value,"");
+  static_assert(std::is_nothrow_convertible<std::tuple<B&,int&&>,BBT>::value,"");
+
+  static_assert(!std::is_nothrow_convertible<IBT,BBT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const IBT,BBT>::value,"");
+  static_assert(!std::is_nothrow_convertible<IBT&,BBT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const IBT &,BBT>::value,"");
+  static_assert(!std::is_nothrow_convertible<IBP,BBT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const IBP,BBT>::value,"");
+  static_assert(!std::is_nothrow_convertible<IBP&,BBT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const IBP &,BBT>::value,"");
+  static_assert(!std::is_nothrow_convertible<std::tuple<B&,int&>,BBT>::value,"");
+
+
+  static_assert(!std::is_nothrow_constructible<BBT,int&,const int&>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,int&&,const B&>::value,"");
+
+  static_assert(std::is_nothrow_constructible<BBT,B&,const B&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,B&&,const B&&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const B &&,const int&&>::value,"");
+
+/* explicit */
+  static_assert(std::is_nothrow_constructible<DDT,IIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,IIT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IIT &>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,IIP>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IIP>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,IIP&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IIP &>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,std::tuple<int&,int&>>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<DDT,DDT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const DDT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,DDT&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const DDT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,DDP>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const DDP>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,DDP&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const DDP &>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,std::tuple<D&,D&>>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<DDT,IDT>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IDT>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,IDT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IDT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,IDP>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IDP>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,IDP&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IDP &>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,std::tuple<const D&,int&&>>::value,"");
+
+  static_assert(!std::is_nothrow_convertible<DDT,DDT>::value,"");
+  static_assert(std::is_nothrow_convertible<const DDT,DDT>::value,"");
+  static_assert(std::is_nothrow_convertible<DDT&,DDT>::value,"");
+  static_assert(std::is_nothrow_convertible<const DDT &,DDT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<DDT,int&,const int&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,int&&,const D&>::value,"");
+
+  static_assert(std::is_nothrow_constructible<DDT,D&,const D&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,D&&,const D&&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const D &&,const int&&>::value,"");
+
+/* three elements tests */
+  static_assert(std::is_nothrow_constructible<BBBT,IIIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBBT,const IIIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBBT,IIIT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBBT,const IIIT &>::value,"");
+
+  static_assert(std::is_nothrow_convertible<IIIT,BBBT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const IIIT,BBBT>::value,"");
+  static_assert(!std::is_nothrow_convertible<IIIT&,BBBT>::value,"");
+  static_assert(!std::is_nothrow_convertible<const IIIT &,BBBT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<BBBT,BBBT>::value,"");
+  static_assert(std::is_nothrow_constructible<BBBT,const BBBT>::value,"");
+  static_assert(std::is_nothrow_constructible<BBBT,BBBT&>::value,"");
+  static_assert(std::is_nothrow_constructible<BBBT,const BBBT &>::value,"");
+
+  static_assert(!std::is_nothrow_convertible<BBBT,BBBT>::value,"");
+  static_assert(std::is_nothrow_convertible<const BBBT,BBBT>::value,"");
+  static_assert(std::is_nothrow_convertible<BBBT&,BBBT>::value,"");
+  static_assert(std::is_nothrow_convertible<const BBBT &,BBBT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<BBBT,int&,const int&,int&&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBBT,int&, B&&,const int&&>::value,"");
+  static_assert(std::is_nothrow_constructible<BBBT,int&&, B&,const B&&>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<BBBT,std::tuple<int&,const int&,int&&>>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBBT,std::tuple<int &, B&&,const int&&>>::value,"");
+  static_assert(std::is_nothrow_constructible<BBBT,std::tuple<int &&, B&,const B&&>>::value,"");
+
+/* explicit */
+  static_assert(std::is_nothrow_constructible<DDDT,IIIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDDT,const IIIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDDT,IIIT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDDT,const IIIT &>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<DDDT,DDDT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDDT,const DDDT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDDT,DDDT&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDDT,const DDDT &>::value,"");
+
+  static_assert(!std::is_nothrow_convertible<DDDT,DDDT>::value,"");
+  static_assert(std::is_nothrow_convertible<const DDDT,DDDT>::value,"");
+  static_assert(std::is_nothrow_convertible<DDDT&,DDDT>::value,"");
+  static_assert(std::is_nothrow_convertible<const DDDT &,DDDT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<DDDT,int&,const int&,int&&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDDT,int &, D&&,const int&&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDDT,int &&, D&,const D&&>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<DDDT,std::tuple<int&,const int&,int&&>>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDDT,std::tuple<int &, D&&,const int&&>>::value,"");
+  static_assert(std::is_nothrow_constructible<DDDT,std::tuple<int &&, D&,const D&&>>::value,"");
+
+
+  void Run()
+  {
+    VERIFY( (checkCopyThrowConstruct<BT, int>()) );
+    VERIFY( (checkMoveThrowConstruct<BT, int>()) );
+    VERIFY( (checkCopyThrowConstruct<BT, B>()) );
+    VERIFY( (checkMoveThrowConstruct<BT, B>()) );
+    VERIFY( (checkCopyThrowConstruct<BT, IT>()) );
+    VERIFY( (checkMoveThrowConstruct<BT, IT>()) );
+    VERIFY( (checkMoveThrowConstruct<BT, CIT>()) );
+    VERIFY( (checkCopyThrowConstruct<BBT, IIT>()) );
+    VERIFY( (checkMoveThrowConstruct<BBT, IIT>()) );
+    VERIFY( (checkCopyThrowConstruct<BBT, IIP>()) );
+    VERIFY( (checkMoveThrowConstruct<BBT, IIP>()) );
+    VERIFY( (checkCopyThrowConstruct<BBT, BBP>()) );
+    VERIFY( (checkMoveThrowConstruct<BBT, BBP>()) );
+    VERIFY( (checkCopyThrowConstruct<BBT, std::tuple<B, int>>()) );
+    VERIFY( (checkMoveThrowConstruct<BBT, std::tuple<B, int>>()) );
+
+    VERIFY( (checkCopyThrowConstruct<DT, int>()) );
+    VERIFY( (checkMoveThrowConstruct<DT, int>()) );
+    VERIFY( (checkCopyThrowConstruct<DT, D>()) );
+    VERIFY( (checkMoveThrowConstruct<DT, D>()) );
+    VERIFY( (checkCopyThrowConstruct<DT, IT>()) );
+    VERIFY( (checkMoveThrowConstruct<DT, IT>()) );
+    VERIFY( (checkMoveThrowConstruct<DT, CIT>()) );
+    VERIFY( (checkCopyThrowConstruct<DDT, IIT>()) );
+    VERIFY( (checkMoveThrowConstruct<DDT, IIT>()) );
+    VERIFY( (checkCopyThrowConstruct<DDT, IIP>()) );
+    VERIFY( (checkMoveThrowConstruct<DDT, IIP>()) );
+    VERIFY( (checkCopyThrowConstruct<DDT, DDP>()) );
+    VERIFY( (checkMoveThrowConstruct<DDT, DDP>()) );
+    VERIFY( (checkCopyThrowConstruct<DDT, std::tuple<D, int>>()) );
+    VERIFY( (checkMoveThrowConstruct<DDT, std::tuple<D, int>>()) );
+
+    VERIFY( (checkCopyThrowConstruct<DBT, IIT>()) );
+    VERIFY( (checkMoveThrowConstruct<DBT, IIT>()) );
+    VERIFY( (checkCopyThrowConstruct<DBT, DBT>()) );
+    VERIFY( (checkMoveThrowConstruct<DBT, DBT>()) );
+    VERIFY( (checkCopyThrowConstruct<DBT, DBP>()) );
+    VERIFY( (checkMoveThrowConstruct<DBT, DBP>()) );
+    VERIFY( (checkCopyThrowConstruct<DBT, IIP>()) );
+    VERIFY( (checkMoveThrowConstruct<DBT, IIP>()) );
+
+
+    VERIFY( (checkCopyThrowConstruct<IDIT, IIIT>()) );
+    VERIFY( (checkMoveThrowConstruct<IDIT, IIIT>()) );
+    VERIFY( (checkCopyThrowConstruct<IDIT, IDIT>()) );
+    VERIFY( (checkMoveThrowConstruct<IDIT, IDIT>()) );
+    VERIFY( (checkCopyThrowConstruct<IBIT, IIIT>()) );
+    VERIFY( (checkMoveThrowConstruct<IBIT, IIIT>()) );
+    VERIFY( (checkCopyThrowConstruct<IBIT, IBIT>()) );
+    VERIFY( (checkMoveThrowConstruct<IBIT, IBIT>()) );
+    VERIFY( (checkCopyThrowConstruct<IDBT, IIIT>()) );
+    VERIFY( (checkMoveThrowConstruct<IDBT, IIIT>()) );
+    VERIFY( (checkCopyThrowConstruct<IDBT, IDBT>()) );
+    VERIFY( (checkMoveThrowConstruct<IDBT, IDBT>()) );
+
+  }
+
+}
+
+
+int main()
+{
+  NothrowCopyThrowMoveThrowCopyConversionNothrowMoveConversion::Run();
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs5.cc
===================================================================
--- libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs5.cc	(nonexistent)
+++ libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs5.cc	(working copy)
@@ -0,0 +1,141 @@
+// { dg-options { -std=gnu++2a } }
+// { dg-do compile { target c++17 } }
+
+// 2019-04-10  Nina Dinka Ranns  <dinka.ranns@gmail.com>
+//
+// Copyright (C) 2017 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>
+#include <testsuite_tr1.h>
+#include <utility>
+
+using namespace __gnu_test;
+
+/* no throw copy */
+
+
+typedef std::tuple<int> IT;
+typedef std::tuple<const int> CIT;
+typedef std::tuple<int&&> RVIT;
+typedef std::tuple<int, int> IIT;
+typedef std::pair<int, int> IIP;
+typedef std::tuple<int, int, int> IIIT;
+
+
+namespace ThrowCopy
+{
+  struct C
+  {
+    C() noexcept(true)
+       {}
+
+    explicit
+    C(const C&) noexcept(true) {}
+
+  };
+
+  typedef std::tuple<C> CT;
+  typedef std::tuple<C,C> CCT;
+  typedef std::pair<C,C> CCP;
+  typedef std::tuple<int,int,C> IICT;
+
+  static_assert(std::is_nothrow_constructible<CT, C&>::value, "");
+  static_assert(std::is_nothrow_constructible<CT, const C&>::value, "");
+  static_assert(std::is_nothrow_constructible<CT, C&&>::value, "");
+  static_assert(std::is_nothrow_constructible<CT, const C &&>::value, "");
+
+
+  static_assert(std::is_nothrow_constructible<CCT, C&, C&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, const C&, const C&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, C&&, C&&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, const C &&, const C &&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IICT, int, int, C&>::value, "");
+  static_assert(std::is_nothrow_constructible<IICT, int, int, const C&>::value, "");
+  static_assert(std::is_nothrow_constructible<IICT, int, int, C&&>::value, "");
+  static_assert(std::is_nothrow_constructible<IICT, int, int, const C &&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<CT, CT&>::value, "");
+  static_assert(std::is_nothrow_constructible<CT, const CT&>::value, "");
+  static_assert(std::is_nothrow_constructible<CT, CT&&>::value, "");
+  static_assert(std::is_nothrow_constructible<CT, const CT &&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<CCT, CCT&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, const CCT&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, CCT&&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, const CCT &&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<CCT, CCP&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, const CCP&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, CCP&&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, const CCP &&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IICT, IICT&>::value, "");
+  static_assert(std::is_nothrow_constructible<IICT, const IICT&>::value, "");
+  static_assert(std::is_nothrow_constructible<IICT, IICT&&>::value, "");
+  static_assert(std::is_nothrow_constructible<IICT, const IICT &&>::value, "");
+
+}
+int main()
+{
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs6.cc
===================================================================
--- libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs6.cc	(nonexistent)
+++ libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs6.cc	(working copy)
@@ -0,0 +1,187 @@
+// { dg-options { -std=gnu++2a } }
+// { dg-do run { target c++17 } }
+
+// 2019-04-10  Nina Dinka Ranns  <dinka.ranns@gmail.com>
+//
+// Copyright (C) 2017 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>
+#include <testsuite_tr1.h>
+#include <utility>
+
+using namespace __gnu_test;
+
+/* throw move, no throw conversion */
+
+bool throwing_ctor_called = false;
+
+template<typename T, typename U>
+bool  checkCopyThrowConstruct()
+{
+  throwing_ctor_called = false;
+  bool deduced_nothrow = std::is_nothrow_constructible<T, U&>::value;
+  U u;
+  T t{u};
+  return throwing_ctor_called != deduced_nothrow;
+}
+template<typename T, typename U>
+bool  checkMoveThrowConstruct()
+{
+  throwing_ctor_called = false;
+  bool deduced_nothrow = std::is_nothrow_constructible<T, U&&>::value;
+  U u;
+  T t{std::move(u)};
+  return throwing_ctor_called != deduced_nothrow;
+}
+
+typedef std::tuple<int> IT;
+typedef std::tuple<const int> CIT;
+typedef std::tuple<int&&> RVIT;
+typedef std::tuple<int, int> IIT;
+typedef std::pair<int, int> IIP;
+typedef std::tuple<int, int, int> IIIT;
+
+namespace ThrowMoveNothrowConversion
+{
+  struct D
+  {
+  D() noexcept(true)
+  {}
+
+  explicit
+  D(const int&) noexcept(true)
+  {}
+
+  explicit
+  D(int&&) noexcept(false)
+  {  throwing_ctor_called = true; }
+
+  };
+
+  typedef std::tuple<D> DT;
+  typedef std::tuple<D,D> DDT;
+  typedef std::pair<D,D> DDP;
+  typedef std::tuple<int,D,int> IDIT;
+
+
+  static_assert(!std::is_nothrow_constructible<DT, int>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const int>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, int&>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const int &>::value, "");
+
+  static_assert(!std::is_nothrow_constructible<DT, IT>::value, "");
+  static_assert(std::is_nothrow_constructible<DT,const IT>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, IT&>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const IT &>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, std::tuple<int&>>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const std::tuple<int&&>>::value, "");
+
+  static_assert(std::is_nothrow_convertible<DT,DT>::value,"");
+  static_assert(std::is_nothrow_convertible<D,DT>::value,"");
+
+/* two elements tests */
+  static_assert(!std::is_nothrow_constructible<DDT,IIT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const IIT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,IIT&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const IIT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,IIP>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const IIP>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,IIP&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const IIP &>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,std::tuple<int&,int&>>::value,"");
+
+  static_assert(std::is_nothrow_constructible<DDT,DDT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,DDP>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,std::tuple<int&,D>>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,std::pair<D,int&&>>::value,"");
+
+  static_assert(std::is_convertible<DDT,DDT>::value,"");
+
+/* three elements tests */
+  static_assert(!std::is_nothrow_constructible<IDIT,IIIT>::value,"");
+  static_assert(std::is_nothrow_constructible<IDIT,const IIIT>::value,"");
+  static_assert(std::is_nothrow_constructible<IDIT,IIIT&>::value,"");
+  static_assert(std::is_nothrow_constructible<IDIT,const IIIT &>::value,"");
+
+  static_assert(std::is_nothrow_convertible<IDIT,IDIT>::value,"");
+  static_assert(std::is_nothrow_convertible<IDIT,IDIT>::value,"");
+
+  static_assert(std::is_nothrow_constructible<IDIT,int&,const int&,int&&>::value,"");
+  static_assert(std::is_nothrow_constructible<IDIT,int &, D&&,const int&&>::value,"");
+  static_assert(std::is_nothrow_constructible<IDIT,std::tuple<int&,const int&,int&&>>::value,"");
+  static_assert(!std::is_nothrow_constructible<IDIT,std::tuple<int &, int&&,const int&&>>::value,"");
+
+  void Run()
+  {
+    VERIFY( (checkCopyThrowConstruct<DDT, IIT>()) );
+    VERIFY( (checkMoveThrowConstruct<DDT, IIT>()) );
+    VERIFY( (checkCopyThrowConstruct<DDT, std::tuple<D, int>>()) );
+    VERIFY( (checkMoveThrowConstruct<DDT, std::tuple<D, int>>()) );
+  }
+}
+
+int main()
+{
+
+  ThrowMoveNothrowConversion::Run();
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Adding noexcept-specification on tuple constructors (LWG 2899)
  2019-04-16 13:28 Adding noexcept-specification on tuple constructors (LWG 2899) Nina Dinka Ranns
@ 2019-04-16 14:25 ` Jonathan Wakely
  2019-04-16 15:24   ` Ville Voutilainen
  2019-04-16 17:06   ` Nina Dinka Ranns
  0 siblings, 2 replies; 14+ messages in thread
From: Jonathan Wakely @ 2019-04-16 14:25 UTC (permalink / raw)
  To: Nina Dinka Ranns; +Cc: gcc-patches, libstdc++

On 16/04/19 14:08 +0100, Nina Dinka Ranns wrote:
>Tested on Linux-PPC64
>Adding noexcept-specification on tuple constructors (LWG 2899)

Thanks, Nina!

This looks great, although as I think Ville has explained we won't
commit it until the next stage 1, after the GCC 9 release.

The changes look good, I just have some mostly-stylistic comments,
which are inline below ...


>2019-04-13 Nina Dinka Ranns <dinka.ranns@gmail.com>
>
>        Adding noexcept-specification on tuple constructors (LWG 2899)
>        * libstdc++-v3/include/std/tuple:
>        (tuple()): Add noexcept-specification.
>        (tuple(const _Elements&...)): Likewise
>        (tuple(_UElements&&...)): Likewise
>        (tuple(const tuple<_UElements...>&)): Likewise
>        (tuple(tuple<_UElements...>&&)): Likewise
>        (tuple(const _T1&, const _T2&)): Likewise
>        (tuple(_U1&&, _U2&&)): Likewise
>        (tuple(const tuple<_U1, _U2>&): Likewise
>        (tuple(tuple<_U1, _U2>&&): Likewise
>        (tuple(const pair<_U1, _U2>&): Likewise
>        (tuple(pair<_U1, _U2>&&): Likewise
>
>

There should be no blank lines in the changelog entry here. A single
change should be recorded as a single block in the changelog, with no
blank lines within it.

>        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc: New
>        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs2.cc: New
>        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs3.cc: New
>        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs4.cc: New
>        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs5.cc: New
>        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs6.cc: New

This is a lot of new test files for a small-ish QoI feature. Could
they be combined into one file?  Generally we do want one test file
per feature, but I think all of these are arguably testing one feature
(just on different constructors). The downside of lots of smaller
files is that we have to compile+assemble+link+run each one, which
adds several fork()s to launch a new process for each step. On some
platforms that can be quite slow.


>@@ -624,6 +634,7 @@
>                   && (sizeof...(_Elements) >= 1),
>         bool>::type=true>
>         constexpr tuple(_UElements&&... __elements)
>+        noexcept(__and_<is_nothrow_constructible<_Elements,_UElements&&>...>::value)

Can this be __nothrow_constructible<_UElements>() ?

>         : _Inherited(std::forward<_UElements>(__elements)...) { }
> 
>       template<typename... _UElements, typename
>@@ -635,6 +646,7 @@
>                   && (sizeof...(_Elements) >= 1),
>         bool>::type=false>
>         explicit constexpr tuple(_UElements&&... __elements)
>+        noexcept(__nothrow_constructible<_UElements&&...>())

The && here is redundant, though harmless.

is_constructible<T,U&&> is exactly equivalent to is_constructible<T,U>
because U means construction from an rvalue of type U and so does U&&.

It's fine to leave the && there though.


>@@ -966,6 +995,7 @@
> 	          && !is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value,
> 	bool>::type = true>
>         constexpr tuple(_U1&& __a1, _U2&& __a2)
>+        noexcept(__nothrow_constructible<_U1&&,_U2&&>())

There should be a space after the comma here, and all the later
additions in the file.


>Index: libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc
>===================================================================
>--- libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc	(nonexistent)
>+++ libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc	(working copy)
>@@ -0,0 +1,191 @@
>+// { dg-options { -std=gnu++2a } }
>+// { dg-do run { target c++2a } }

This new file doesn't use std::is_nothrow_convertible so could just
use: { dg-do run { target c++11 } } and no dg-options.

For the other new tests that do use is_nothrow_convertible, I'm
already planning to add std::is_nothrow_convertible for our internal
use in C++11, so they could use that.

Alternatively, the test files themselves could define:

template<typename From, typename To>
  struct is_nothrow_convertible
  : std::integral_constant<bool,
      is_convertible<From, To> && is_nothrow_constructible<Fo, From>>
  { };

and then use that. That way we can test the exception specs are
correct in C++11 mode, the default C++14 mode, and C++17 mode.
Otherwise we're adding code that affects all those modes but only
testing it works correctly for the experimental C++2a mode.


>+// 2019-04-10  Nina Dinka Ranns  <dinka.ranns@gmail.com>
>+//
>+// Copyright (C) 2017 Free Software Foundation, Inc.

Copyright date on new files should be 2019.

>+//
>+// 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>
>+#include <testsuite_tr1.h>
>+#include <utility>
>+
>+/* DefaultConstructionTests */
>+
>+using namespace __gnu_test;
>+
>+bool throwing_ctor_called = false;
>+
>+
>+template<typename T>
>+bool  checkDefaultThrowConstruct()
>+{
>+  throwing_ctor_called = false;
>+  bool deduced_nothrow = std::is_nothrow_constructible<T>::value;
>+  T t{};
>+  return throwing_ctor_called != deduced_nothrow;
>+}
>+
>+
>+typedef std::tuple<int> IT;
>+typedef std::tuple<const int> CIT;
>+typedef std::tuple<int&&> RVIT;
>+typedef std::tuple<int, int> IIT;
>+typedef std::pair<int, int> IIP;
>+typedef std::tuple<int, int, int> IIIT;
>+
>+namespace DefaultConstructionTests
>+{
>+  struct NoexceptDC
>+  {
>+    NoexceptDC() noexcept(true){}
>+  };
>+
>+  struct ExceptDC
>+  {
>+    ExceptDC() noexcept(false)
>+      {  throwing_ctor_called = true; }
>+  };
>+
>+  struct ExplicitNoexceptDC
>+  {
>+    explicit ExplicitNoexceptDC() noexcept(true)
>+        {}
>+  };
>+
>+  struct ExplicitExceptDC
>+  {
>+    explicit ExplicitExceptDC() noexcept(false)
>+        {  throwing_ctor_called = true; }
>+  };
>+
>+  typedef std::tuple<NoexceptDC> NDT;
>+  typedef std::tuple<ExceptDC> EDT;
>+  typedef std::tuple<ExplicitNoexceptDC> X_NDT;
>+  typedef std::tuple<ExplicitExceptDC> X_EDT;
>+
>+  typedef std::tuple<NoexceptDC,NoexceptDC> NNDT;
>+  typedef std::tuple<ExceptDC,ExceptDC> EEDT;
>+  typedef std::tuple<ExceptDC,NoexceptDC> ENDT;
>+  typedef std::tuple<ExplicitNoexceptDC,NoexceptDC> X_NNDT;
>+  typedef std::tuple<ExplicitExceptDC,ExceptDC> X_EEDT;
>+  typedef std::tuple<ExceptDC,ExplicitNoexceptDC> X_ENDT;
>+
>+  typedef std::tuple<long, NoexceptDC, NoexceptDC> LNDNDT;
>+  typedef std::tuple<long, NoexceptDC, ExceptDC> LNDEDT;
>+  typedef std::tuple<long, ExplicitNoexceptDC, NoexceptDC> X_LNEDNDT;
>+  typedef std::tuple<long, ExplicitNoexceptDC, ExceptDC> X_LNEDEDT;
>+  typedef std::tuple<long, ExplicitExceptDC, ExceptDC> X_LEEDEDT;
>+
>+
>+  /* if it has E in the name, it contains a type that throws when default constructed */
>+  static_assert(std::is_nothrow_constructible<IT>::value, "");
>+  static_assert(std::is_nothrow_constructible<NDT>::value, "");
>+  static_assert(!std::is_nothrow_constructible<EDT>::value, "");
>+  static_assert(std::is_nothrow_constructible<X_NDT>::value, "");
>+  static_assert(!std::is_nothrow_constructible<X_EDT>::value, "");
>+
>+  static_assert(std::is_nothrow_constructible<IIT>::value, "");
>+  static_assert(std::is_nothrow_constructible<NNDT>::value, "");
>+  static_assert(!std::is_nothrow_constructible<EEDT>::value, "");
>+  static_assert(!std::is_nothrow_constructible<ENDT>::value, "");
>+  static_assert(std::is_nothrow_constructible<X_NNDT>::value, "");
>+  static_assert(!std::is_nothrow_constructible<X_EEDT>::value, "");
>+  static_assert(!std::is_nothrow_constructible<X_ENDT>::value, "");
>+
>+  static_assert(std::is_nothrow_constructible<IIIT>::value, "");
>+  static_assert(std::is_nothrow_constructible<LNDNDT>::value, "");
>+  static_assert(!std::is_nothrow_constructible<LNDEDT>::value, "");
>+  static_assert(std::is_nothrow_constructible<X_LNEDNDT>::value, "");
>+  static_assert(!std::is_nothrow_constructible<X_LNEDEDT>::value, "");
>+  static_assert(!std::is_nothrow_constructible<X_LEEDEDT>::value, "");
>+
>+  void Run()
>+  {
>+    VERIFY( checkDefaultThrowConstruct<IT>() );
>+    VERIFY( checkDefaultThrowConstruct<NDT>() );
>+    VERIFY( checkDefaultThrowConstruct<EDT>() );
>+    VERIFY( checkDefaultThrowConstruct<X_NDT>() );
>+    VERIFY( checkDefaultThrowConstruct<X_EDT>() );
>+
>+    VERIFY( checkDefaultThrowConstruct<IIT>() );
>+    VERIFY( checkDefaultThrowConstruct<NNDT>() );
>+    VERIFY( checkDefaultThrowConstruct<EEDT>() );
>+    VERIFY( checkDefaultThrowConstruct<ENDT>() );
>+    VERIFY( checkDefaultThrowConstruct<X_NNDT>() );
>+    VERIFY( checkDefaultThrowConstruct<X_EEDT>() );
>+    VERIFY( checkDefaultThrowConstruct<X_ENDT>() );
>+
>+    VERIFY( checkDefaultThrowConstruct<IIIT>() );
>+    VERIFY( checkDefaultThrowConstruct<LNDNDT>() );
>+    VERIFY( checkDefaultThrowConstruct<LNDEDT>() );
>+    VERIFY( checkDefaultThrowConstruct<X_LNEDNDT>() );
>+    VERIFY( checkDefaultThrowConstruct<X_LNEDEDT>() );
>+  }
>+}
>+
>+
>+int main()
>+{
>+
>+  DefaultConstructionTests::Run();
>+
>+}
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+
>+

These blank lines should go.

>Index: libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs2.cc
>===================================================================
>--- libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs2.cc	(nonexistent)
>+++ libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs2.cc	(working copy)
>@@ -0,0 +1,129 @@
>+// { dg-options { -std=gnu++2a } }
>+// { dg-do run { target c++2a } }

This one has an empty main() function, so could be a { dg-do compile }
test instead (and then it doesn't need a main() function). Although if
you combine all the new test files into one file then it will have a
non-empty main(), and will need to be { dg-do run }, so this comment
is just FYI really.


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Adding noexcept-specification on tuple constructors (LWG 2899)
  2019-04-16 14:25 ` Jonathan Wakely
@ 2019-04-16 15:24   ` Ville Voutilainen
  2019-04-16 17:06   ` Nina Dinka Ranns
  1 sibling, 0 replies; 14+ messages in thread
From: Ville Voutilainen @ 2019-04-16 15:24 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: Nina Dinka Ranns, gcc-patches List, libstdc++

On Tue, 16 Apr 2019 at 17:18, Jonathan Wakely <jwakely@redhat.com> wrote:
> >--- libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc        (nonexistent)
> >+++ libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc        (working copy)
> >@@ -0,0 +1,191 @@
> >+// { dg-options { -std=gnu++2a } }
> >+// { dg-do run { target c++2a } }
>
> This new file doesn't use std::is_nothrow_convertible so could just
> use: { dg-do run { target c++11 } } and no dg-options.
>
> For the other new tests that do use is_nothrow_convertible, I'm
> already planning to add std::is_nothrow_convertible for our internal
> use in C++11, so they could use that.
>
> Alternatively, the test files themselves could define:
>
> template<typename From, typename To>
>   struct is_nothrow_convertible
>   : std::integral_constant<bool,
>       is_convertible<From, To> && is_nothrow_constructible<Fo, From>>
>   { };
>
> and then use that. That way we can test the exception specs are
> correct in C++11 mode, the default C++14 mode, and C++17 mode.
> Otherwise we're adding code that affects all those modes but only
> testing it works correctly for the experimental C++2a mode.

That doesn't look right to me. If we go down the path of defining the
trait in the tests, let's please
copy the implementation of std::is_nothrow_convertible, which properly
uses a noexcept-check of a helper function
call (which makes the conversion be copy-initialization, since it's on
a function parameter). Otherwise,
https://wandbox.org/permlink/ALXkVVANdD4Z2AZm

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Adding noexcept-specification on tuple constructors (LWG 2899)
  2019-04-16 14:25 ` Jonathan Wakely
  2019-04-16 15:24   ` Ville Voutilainen
@ 2019-04-16 17:06   ` Nina Dinka Ranns
  2019-04-18 20:43     ` Jonathan Wakely
  1 sibling, 1 reply; 14+ messages in thread
From: Nina Dinka Ranns @ 2019-04-16 17:06 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: gcc-patches, libstdc++

On Tue, 16 Apr 2019 at 15:18, Jonathan Wakely <jwakely@redhat.com> wrote:
>
> On 16/04/19 14:08 +0100, Nina Dinka Ranns wrote:
> >Tested on Linux-PPC64
> >Adding noexcept-specification on tuple constructors (LWG 2899)
>
> Thanks, Nina!
>
> This looks great, although as I think Ville has explained we won't
> commit it until the next stage 1, after the GCC 9 release.
ack

>
> The changes look good, I just have some mostly-stylistic comments,
> which are inline below ...
>
>
> >2019-04-13 Nina Dinka Ranns <dinka.ranns@gmail.com>
> >
> >        Adding noexcept-specification on tuple constructors (LWG 2899)
> >        * libstdc++-v3/include/std/tuple:
> >        (tuple()): Add noexcept-specification.
> >        (tuple(const _Elements&...)): Likewise
> >        (tuple(_UElements&&...)): Likewise
> >        (tuple(const tuple<_UElements...>&)): Likewise
> >        (tuple(tuple<_UElements...>&&)): Likewise
> >        (tuple(const _T1&, const _T2&)): Likewise
> >        (tuple(_U1&&, _U2&&)): Likewise
> >        (tuple(const tuple<_U1, _U2>&): Likewise
> >        (tuple(tuple<_U1, _U2>&&): Likewise
> >        (tuple(const pair<_U1, _U2>&): Likewise
> >        (tuple(pair<_U1, _U2>&&): Likewise
> >
> >
>
> There should be no blank lines in the changelog entry here. A single
> change should be recorded as a single block in the changelog, with no
> blank lines within it.
ack. Do you need me to do anything about this or is it for future
reference only ?

>
> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc: New
> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs2.cc: New
> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs3.cc: New
> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs4.cc: New
> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs5.cc: New
> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs6.cc: New
>
> This is a lot of new test files for a small-ish QoI feature. Could
> they be combined into one file?  Generally we do want one test file
> per feature, but I think all of these are arguably testing one feature
> (just on different constructors). The downside of lots of smaller
> files is that we have to compile+assemble+link+run each one, which
> adds several fork()s to launch a new process for each step. On some
> platforms that can be quite slow.
I can do that, but there may be an issue. See below.

>
>
> >@@ -624,6 +634,7 @@
> >                   && (sizeof...(_Elements) >= 1),
> >         bool>::type=true>
> >         constexpr tuple(_UElements&&... __elements)
> >+        noexcept(__and_<is_nothrow_constructible<_Elements,_UElements&&>...>::value)
>
> Can this be __nothrow_constructible<_UElements>() ?
It should have been that in the first place. Apologies. Fixed.


>
> >         : _Inherited(std::forward<_UElements>(__elements)...) { }
> >
> >       template<typename... _UElements, typename
> >@@ -635,6 +646,7 @@
> >                   && (sizeof...(_Elements) >= 1),
> >         bool>::type=false>
> >         explicit constexpr tuple(_UElements&&... __elements)
> >+        noexcept(__nothrow_constructible<_UElements&&...>())
>
> The && here is redundant, though harmless.
>
> is_constructible<T,U&&> is exactly equivalent to is_constructible<T,U>
> because U means construction from an rvalue of type U and so does U&&.
>
> It's fine to leave the && there though.
I'm happy to go either way. The only reason I used && form is because
it mimics the wording in the LWG resolution.

>
>
> >@@ -966,6 +995,7 @@
> >                 && !is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value,
> >       bool>::type = true>
> >         constexpr tuple(_U1&& __a1, _U2&& __a2)
> >+        noexcept(__nothrow_constructible<_U1&&,_U2&&>())
>
> There should be a space after the comma here, and all the later
> additions in the file.
ack. Fixed

>
>
> >Index: libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc
> >===================================================================
> >--- libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc        (nonexistent)
> >+++ libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc        (working copy)
> >@@ -0,0 +1,191 @@
> >+// { dg-options { -std=gnu++2a } }
> >+// { dg-do run { target c++2a } }
>
> This new file doesn't use std::is_nothrow_convertible so could just
> use: { dg-do run { target c++11 } } and no dg-options.
>
> For the other new tests that do use is_nothrow_convertible, I'm
> already planning to add std::is_nothrow_convertible for our internal
> use in C++11, so they could use that.
>
> Alternatively, the test files themselves could define:
>
> template<typename From, typename To>
>   struct is_nothrow_convertible
>   : std::integral_constant<bool,
>       is_convertible<From, To> && is_nothrow_constructible<Fo, From>>
>   { };
>
> and then use that. That way we can test the exception specs are
> correct in C++11 mode, the default C++14 mode, and C++17 mode.
> Otherwise we're adding code that affects all those modes but only
> testing it works correctly for the experimental C++2a mode.

There is a reason why the tests are only C++2a mode. The semantics of
copy construction changed between C++14 and C++17, the effect of which
is that the is_nothrow_convertible (or its equivalent work around) in
certain cases doesn't evaluate the same before and after C++17. After
discussing this with Ville, we decided to only test C++2a because
that's the target of the library issue and because C++2a provided
std::is_nothrow_convertible so I could do away with my copy conversion
helper functions.
Extending the tests to earlier standards would mean having two sets of
test expectations (one for pre C++17 copy conversion semantics, and
one for C++17 onwards). Would you like me to do that ?

I will address other tests comments when I have an agreement on what
to do with the above issue.
>
>
> >+// 2019-04-10  Nina Dinka Ranns  <dinka.ranns@gmail.com>
> >+//
> >+// Copyright (C) 2017 Free Software Foundation, Inc.
>
> Copyright date on new files should be 2019.
>
> >+//
> >+// 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>
> >+#include <testsuite_tr1.h>
> >+#include <utility>
> >+
> >+/* DefaultConstructionTests */
> >+
> >+using namespace __gnu_test;
> >+
> >+bool throwing_ctor_called = false;
> >+
> >+
> >+template<typename T>
> >+bool  checkDefaultThrowConstruct()
> >+{
> >+  throwing_ctor_called = false;
> >+  bool deduced_nothrow = std::is_nothrow_constructible<T>::value;
> >+  T t{};
> >+  return throwing_ctor_called != deduced_nothrow;
> >+}
> >+
> >+
> >+typedef std::tuple<int> IT;
> >+typedef std::tuple<const int> CIT;
> >+typedef std::tuple<int&&> RVIT;
> >+typedef std::tuple<int, int> IIT;
> >+typedef std::pair<int, int> IIP;
> >+typedef std::tuple<int, int, int> IIIT;
> >+
> >+namespace DefaultConstructionTests
> >+{
> >+  struct NoexceptDC
> >+  {
> >+    NoexceptDC() noexcept(true){}
> >+  };
> >+
> >+  struct ExceptDC
> >+  {
> >+    ExceptDC() noexcept(false)
> >+      {  throwing_ctor_called = true; }
> >+  };
> >+
> >+  struct ExplicitNoexceptDC
> >+  {
> >+    explicit ExplicitNoexceptDC() noexcept(true)
> >+        {}
> >+  };
> >+
> >+  struct ExplicitExceptDC
> >+  {
> >+    explicit ExplicitExceptDC() noexcept(false)
> >+        {  throwing_ctor_called = true; }
> >+  };
> >+
> >+  typedef std::tuple<NoexceptDC> NDT;
> >+  typedef std::tuple<ExceptDC> EDT;
> >+  typedef std::tuple<ExplicitNoexceptDC> X_NDT;
> >+  typedef std::tuple<ExplicitExceptDC> X_EDT;
> >+
> >+  typedef std::tuple<NoexceptDC,NoexceptDC> NNDT;
> >+  typedef std::tuple<ExceptDC,ExceptDC> EEDT;
> >+  typedef std::tuple<ExceptDC,NoexceptDC> ENDT;
> >+  typedef std::tuple<ExplicitNoexceptDC,NoexceptDC> X_NNDT;
> >+  typedef std::tuple<ExplicitExceptDC,ExceptDC> X_EEDT;
> >+  typedef std::tuple<ExceptDC,ExplicitNoexceptDC> X_ENDT;
> >+
> >+  typedef std::tuple<long, NoexceptDC, NoexceptDC> LNDNDT;
> >+  typedef std::tuple<long, NoexceptDC, ExceptDC> LNDEDT;
> >+  typedef std::tuple<long, ExplicitNoexceptDC, NoexceptDC> X_LNEDNDT;
> >+  typedef std::tuple<long, ExplicitNoexceptDC, ExceptDC> X_LNEDEDT;
> >+  typedef std::tuple<long, ExplicitExceptDC, ExceptDC> X_LEEDEDT;
> >+
> >+
> >+  /* if it has E in the name, it contains a type that throws when default constructed */
> >+  static_assert(std::is_nothrow_constructible<IT>::value, "");
> >+  static_assert(std::is_nothrow_constructible<NDT>::value, "");
> >+  static_assert(!std::is_nothrow_constructible<EDT>::value, "");
> >+  static_assert(std::is_nothrow_constructible<X_NDT>::value, "");
> >+  static_assert(!std::is_nothrow_constructible<X_EDT>::value, "");
> >+
> >+  static_assert(std::is_nothrow_constructible<IIT>::value, "");
> >+  static_assert(std::is_nothrow_constructible<NNDT>::value, "");
> >+  static_assert(!std::is_nothrow_constructible<EEDT>::value, "");
> >+  static_assert(!std::is_nothrow_constructible<ENDT>::value, "");
> >+  static_assert(std::is_nothrow_constructible<X_NNDT>::value, "");
> >+  static_assert(!std::is_nothrow_constructible<X_EEDT>::value, "");
> >+  static_assert(!std::is_nothrow_constructible<X_ENDT>::value, "");
> >+
> >+  static_assert(std::is_nothrow_constructible<IIIT>::value, "");
> >+  static_assert(std::is_nothrow_constructible<LNDNDT>::value, "");
> >+  static_assert(!std::is_nothrow_constructible<LNDEDT>::value, "");
> >+  static_assert(std::is_nothrow_constructible<X_LNEDNDT>::value, "");
> >+  static_assert(!std::is_nothrow_constructible<X_LNEDEDT>::value, "");
> >+  static_assert(!std::is_nothrow_constructible<X_LEEDEDT>::value, "");
> >+
> >+  void Run()
> >+  {
> >+    VERIFY( checkDefaultThrowConstruct<IT>() );
> >+    VERIFY( checkDefaultThrowConstruct<NDT>() );
> >+    VERIFY( checkDefaultThrowConstruct<EDT>() );
> >+    VERIFY( checkDefaultThrowConstruct<X_NDT>() );
> >+    VERIFY( checkDefaultThrowConstruct<X_EDT>() );
> >+
> >+    VERIFY( checkDefaultThrowConstruct<IIT>() );
> >+    VERIFY( checkDefaultThrowConstruct<NNDT>() );
> >+    VERIFY( checkDefaultThrowConstruct<EEDT>() );
> >+    VERIFY( checkDefaultThrowConstruct<ENDT>() );
> >+    VERIFY( checkDefaultThrowConstruct<X_NNDT>() );
> >+    VERIFY( checkDefaultThrowConstruct<X_EEDT>() );
> >+    VERIFY( checkDefaultThrowConstruct<X_ENDT>() );
> >+
> >+    VERIFY( checkDefaultThrowConstruct<IIIT>() );
> >+    VERIFY( checkDefaultThrowConstruct<LNDNDT>() );
> >+    VERIFY( checkDefaultThrowConstruct<LNDEDT>() );
> >+    VERIFY( checkDefaultThrowConstruct<X_LNEDNDT>() );
> >+    VERIFY( checkDefaultThrowConstruct<X_LNEDEDT>() );
> >+  }
> >+}
> >+
> >+
> >+int main()
> >+{
> >+
> >+  DefaultConstructionTests::Run();
> >+
> >+}
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
> >+
>
> These blank lines should go.
>
> >Index: libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs2.cc
> >===================================================================
> >--- libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs2.cc       (nonexistent)
> >+++ libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs2.cc       (working copy)
> >@@ -0,0 +1,129 @@
> >+// { dg-options { -std=gnu++2a } }
> >+// { dg-do run { target c++2a } }
>
> This one has an empty main() function, so could be a { dg-do compile }
> test instead (and then it doesn't need a main() function). Although if
> you combine all the new test files into one file then it will have a
> non-empty main(), and will need to be { dg-do run }, so this comment
> is just FYI really.
>
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Adding noexcept-specification on tuple constructors (LWG 2899)
  2019-04-16 17:06   ` Nina Dinka Ranns
@ 2019-04-18 20:43     ` Jonathan Wakely
  2019-04-23 19:12       ` Nina Dinka Ranns
  0 siblings, 1 reply; 14+ messages in thread
From: Jonathan Wakely @ 2019-04-18 20:43 UTC (permalink / raw)
  To: Nina Dinka Ranns; +Cc: gcc-patches, libstdc++

On 16/04/19 17:59 +0100, Nina Dinka Ranns wrote:
>On Tue, 16 Apr 2019 at 15:18, Jonathan Wakely <jwakely@redhat.com> wrote:
>>
>> On 16/04/19 14:08 +0100, Nina Dinka Ranns wrote:
>> >Tested on Linux-PPC64
>> >Adding noexcept-specification on tuple constructors (LWG 2899)
>>
>> Thanks, Nina!
>>
>> This looks great, although as I think Ville has explained we won't
>> commit it until the next stage 1, after the GCC 9 release.
>ack
>
>>
>> The changes look good, I just have some mostly-stylistic comments,
>> which are inline below ...
>>
>>
>> >2019-04-13 Nina Dinka Ranns <dinka.ranns@gmail.com>
>> >
>> >        Adding noexcept-specification on tuple constructors (LWG 2899)
>> >        * libstdc++-v3/include/std/tuple:
>> >        (tuple()): Add noexcept-specification.
>> >        (tuple(const _Elements&...)): Likewise
>> >        (tuple(_UElements&&...)): Likewise
>> >        (tuple(const tuple<_UElements...>&)): Likewise
>> >        (tuple(tuple<_UElements...>&&)): Likewise
>> >        (tuple(const _T1&, const _T2&)): Likewise
>> >        (tuple(_U1&&, _U2&&)): Likewise
>> >        (tuple(const tuple<_U1, _U2>&): Likewise
>> >        (tuple(tuple<_U1, _U2>&&): Likewise
>> >        (tuple(const pair<_U1, _U2>&): Likewise
>> >        (tuple(pair<_U1, _U2>&&): Likewise
>> >
>> >
>>
>> There should be no blank lines in the changelog entry here. A single
>> change should be recorded as a single block in the changelog, with no
>> blank lines within it.
>ack. Do you need me to do anything about this or is it for future
>reference only ?

For future reference. Whoever commits the patch can correct the
changelog.

>>
>> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc: New
>> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs2.cc: New
>> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs3.cc: New
>> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs4.cc: New
>> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs5.cc: New
>> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs6.cc: New
>>
>> This is a lot of new test files for a small-ish QoI feature. Could
>> they be combined into one file?  Generally we do want one test file
>> per feature, but I think all of these are arguably testing one feature
>> (just on different constructors). The downside of lots of smaller
>> files is that we have to compile+assemble+link+run each one, which
>> adds several fork()s to launch a new process for each step. On some
>> platforms that can be quite slow.
>I can do that, but there may be an issue. See below.
>
>>
>>
>> >@@ -624,6 +634,7 @@
>> >                   && (sizeof...(_Elements) >= 1),
>> >         bool>::type=true>
>> >         constexpr tuple(_UElements&&... __elements)
>> >+        noexcept(__and_<is_nothrow_constructible<_Elements,_UElements&&>...>::value)
>>
>> Can this be __nothrow_constructible<_UElements>() ?
>It should have been that in the first place. Apologies. Fixed.
>
>
>>
>> >         : _Inherited(std::forward<_UElements>(__elements)...) { }
>> >
>> >       template<typename... _UElements, typename
>> >@@ -635,6 +646,7 @@
>> >                   && (sizeof...(_Elements) >= 1),
>> >         bool>::type=false>
>> >         explicit constexpr tuple(_UElements&&... __elements)
>> >+        noexcept(__nothrow_constructible<_UElements&&...>())
>>
>> The && here is redundant, though harmless.
>>
>> is_constructible<T,U&&> is exactly equivalent to is_constructible<T,U>
>> because U means construction from an rvalue of type U and so does U&&.
>>
>> It's fine to leave the && there though.
>I'm happy to go either way. The only reason I used && form is because
>it mimics the wording in the LWG resolution.

I suspect if STL had reviewed the wording in the resolution he'd have
asked for the && to be removed :-)


>> >@@ -966,6 +995,7 @@
>> >                 && !is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value,
>> >       bool>::type = true>
>> >         constexpr tuple(_U1&& __a1, _U2&& __a2)
>> >+        noexcept(__nothrow_constructible<_U1&&,_U2&&>())
>>
>> There should be a space after the comma here, and all the later
>> additions in the file.
>ack. Fixed
>
>>
>>
>> >Index: libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc
>> >===================================================================
>> >--- libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc        (nonexistent)
>> >+++ libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc        (working copy)
>> >@@ -0,0 +1,191 @@
>> >+// { dg-options { -std=gnu++2a } }
>> >+// { dg-do run { target c++2a } }
>>
>> This new file doesn't use std::is_nothrow_convertible so could just
>> use: { dg-do run { target c++11 } } and no dg-options.
>>
>> For the other new tests that do use is_nothrow_convertible, I'm
>> already planning to add std::is_nothrow_convertible for our internal
>> use in C++11, so they could use that.
>>
>> Alternatively, the test files themselves could define:
>>
>> template<typename From, typename To>
>>   struct is_nothrow_convertible
>>   : std::integral_constant<bool,
>>       is_convertible<From, To> && is_nothrow_constructible<Fo, From>>
>>   { };
>>
>> and then use that. That way we can test the exception specs are
>> correct in C++11 mode, the default C++14 mode, and C++17 mode.
>> Otherwise we're adding code that affects all those modes but only
>> testing it works correctly for the experimental C++2a mode.
>
>There is a reason why the tests are only C++2a mode. The semantics of
>copy construction changed between C++14 and C++17, the effect of which
>is that the is_nothrow_convertible (or its equivalent work around) in
>certain cases doesn't evaluate the same before and after C++17. After
>discussing this with Ville, we decided to only test C++2a because
>that's the target of the library issue and because C++2a provided

But this isn't actually related to the library issue. The proposed
resolution that you're implementing doesn't fix the issue! The
discussion in the issue says "The description doesn't match the
resolution" and that's correct. That's why I've provided a new
resolution to the issue. What you're doing is a Good Thing anyway,
even if it doesn't solve LWG 2899. But since it isn't a fix for 2899,
which version of C++ the issue targets is irrelevant. You're applying
a change that affects std::tuple unconditionally, from C++11 onwards.
You're changing the code for C++11, so it should be tested for C++11.

It would be appropriate to only test C++2a if you were adding
exception specifications that only applied for C++2a, like so:

        constexpr tuple(_UElements&&... __elements)
#if __cplusplus > 201703L
        noexcept(__and_<is_nothrow_constructible<_Elements,_UElements&&>...>::value)
#endif

But that's not what your patch does (and not what we want it to do).

So I really think we need *some* tests that can run in C++11 mode.
They wouldn't have to be as extensive and thorough as the ones you've
provided, but if we make changes that affect C++11/14/17 then we
should test those changes.

>std::is_nothrow_convertible so I could do away with my copy conversion
>helper functions.
>Extending the tests to earlier standards would mean having two sets of
>test expectations (one for pre C++17 copy conversion semantics, and
>one for C++17 onwards). Would you like me to do that ?

Can you show an example of the different semantics? What behaves
differently in C++14?

If the library provided a std::__is_nothrow_convertible trait for
C++11 (with the same implementation as C++20's
std::is_nothrow_convertible) and your tests used that, which test
expectations would be affected?

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Adding noexcept-specification on tuple constructors (LWG 2899)
  2019-04-18 20:43     ` Jonathan Wakely
@ 2019-04-23 19:12       ` Nina Dinka Ranns
  2019-04-23 21:05         ` Jonathan Wakely
  0 siblings, 1 reply; 14+ messages in thread
From: Nina Dinka Ranns @ 2019-04-23 19:12 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: gcc-patches, libstdc++

[-- Attachment #1: Type: text/plain, Size: 8818 bytes --]

On Thu, 18 Apr 2019 at 21:35, Jonathan Wakely <jwakely@redhat.com> wrote:
>
> On 16/04/19 17:59 +0100, Nina Dinka Ranns wrote:
> >On Tue, 16 Apr 2019 at 15:18, Jonathan Wakely <jwakely@redhat.com> wrote:
> >>
> >> On 16/04/19 14:08 +0100, Nina Dinka Ranns wrote:
> >> >Tested on Linux-PPC64
> >> >Adding noexcept-specification on tuple constructors (LWG 2899)
> >>
> >> Thanks, Nina!
> >>
> >> This looks great, although as I think Ville has explained we won't
> >> commit it until the next stage 1, after the GCC 9 release.
> >ack
> >
> >>
> >> The changes look good, I just have some mostly-stylistic comments,
> >> which are inline below ...
> >>
> >>
> >> >2019-04-13 Nina Dinka Ranns <dinka.ranns@gmail.com>
> >> >
> >> >        Adding noexcept-specification on tuple constructors (LWG 2899)
> >> >        * libstdc++-v3/include/std/tuple:
> >> >        (tuple()): Add noexcept-specification.
> >> >        (tuple(const _Elements&...)): Likewise
> >> >        (tuple(_UElements&&...)): Likewise
> >> >        (tuple(const tuple<_UElements...>&)): Likewise
> >> >        (tuple(tuple<_UElements...>&&)): Likewise
> >> >        (tuple(const _T1&, const _T2&)): Likewise
> >> >        (tuple(_U1&&, _U2&&)): Likewise
> >> >        (tuple(const tuple<_U1, _U2>&): Likewise
> >> >        (tuple(tuple<_U1, _U2>&&): Likewise
> >> >        (tuple(const pair<_U1, _U2>&): Likewise
> >> >        (tuple(pair<_U1, _U2>&&): Likewise
> >> >
> >> >
> >>
> >> There should be no blank lines in the changelog entry here. A single
> >> change should be recorded as a single block in the changelog, with no
> >> blank lines within it.
> >ack. Do you need me to do anything about this or is it for future
> >reference only ?
>
> For future reference. Whoever commits the patch can correct the
> changelog.
>
> >>
> >> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc: New
> >> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs2.cc: New
> >> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs3.cc: New
> >> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs4.cc: New
> >> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs5.cc: New
> >> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs6.cc: New
> >>
> >> This is a lot of new test files for a small-ish QoI feature. Could
> >> they be combined into one file?  Generally we do want one test file
> >> per feature, but I think all of these are arguably testing one feature
> >> (just on different constructors). The downside of lots of smaller
> >> files is that we have to compile+assemble+link+run each one, which
> >> adds several fork()s to launch a new process for each step. On some
> >> platforms that can be quite slow.
> >I can do that, but there may be an issue. See below.
> >
> >>
> >>
> >> >@@ -624,6 +634,7 @@
> >> >                   && (sizeof...(_Elements) >= 1),
> >> >         bool>::type=true>
> >> >         constexpr tuple(_UElements&&... __elements)
> >> >+        noexcept(__and_<is_nothrow_constructible<_Elements,_UElements&&>...>::value)
> >>
> >> Can this be __nothrow_constructible<_UElements>() ?
> >It should have been that in the first place. Apologies. Fixed.
> >
> >
> >>
> >> >         : _Inherited(std::forward<_UElements>(__elements)...) { }
> >> >
> >> >       template<typename... _UElements, typename
> >> >@@ -635,6 +646,7 @@
> >> >                   && (sizeof...(_Elements) >= 1),
> >> >         bool>::type=false>
> >> >         explicit constexpr tuple(_UElements&&... __elements)
> >> >+        noexcept(__nothrow_constructible<_UElements&&...>())
> >>
> >> The && here is redundant, though harmless.
> >>
> >> is_constructible<T,U&&> is exactly equivalent to is_constructible<T,U>
> >> because U means construction from an rvalue of type U and so does U&&.
> >>
> >> It's fine to leave the && there though.
> >I'm happy to go either way. The only reason I used && form is because
> >it mimics the wording in the LWG resolution.
>
> I suspect if STL had reviewed the wording in the resolution he'd have
> asked for the && to be removed :-)
:) ack. Removed.


>
>
> >> >@@ -966,6 +995,7 @@
> >> >                 && !is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value,
> >> >       bool>::type = true>
> >> >         constexpr tuple(_U1&& __a1, _U2&& __a2)
> >> >+        noexcept(__nothrow_constructible<_U1&&,_U2&&>())
> >>
> >> There should be a space after the comma here, and all the later
> >> additions in the file.
> >ack. Fixed
> >
> >>
> >>
> >> >Index: libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc
> >> >===================================================================
> >> >--- libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc        (nonexistent)
> >> >+++ libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc        (working copy)
> >> >@@ -0,0 +1,191 @@
> >> >+// { dg-options { -std=gnu++2a } }
> >> >+// { dg-do run { target c++2a } }
> >>
> >> This new file doesn't use std::is_nothrow_convertible so could just
> >> use: { dg-do run { target c++11 } } and no dg-options.
> >>
> >> For the other new tests that do use is_nothrow_convertible, I'm
> >> already planning to add std::is_nothrow_convertible for our internal
> >> use in C++11, so they could use that.
> >>
> >> Alternatively, the test files themselves could define:
> >>
> >> template<typename From, typename To>
> >>   struct is_nothrow_convertible
> >>   : std::integral_constant<bool,
> >>       is_convertible<From, To> && is_nothrow_constructible<Fo, From>>
> >>   { };
> >>
> >> and then use that. That way we can test the exception specs are
> >> correct in C++11 mode, the default C++14 mode, and C++17 mode.
> >> Otherwise we're adding code that affects all those modes but only
> >> testing it works correctly for the experimental C++2a mode.
> >
> >There is a reason why the tests are only C++2a mode. The semantics of
> >copy construction changed between C++14 and C++17, the effect of which
> >is that the is_nothrow_convertible (or its equivalent work around) in
> >certain cases doesn't evaluate the same before and after C++17. After
> >discussing this with Ville, we decided to only test C++2a because
> >that's the target of the library issue and because C++2a provided
>
> But this isn't actually related to the library issue. The proposed
> resolution that you're implementing doesn't fix the issue! The
> discussion in the issue says "The description doesn't match the
> resolution" and that's correct. That's why I've provided a new
> resolution to the issue. What you're doing is a Good Thing anyway,
> even if it doesn't solve LWG 2899. But since it isn't a fix for 2899,
> which version of C++ the issue targets is irrelevant. You're applying
> a change that affects std::tuple unconditionally, from C++11 onwards.
> You're changing the code for C++11, so it should be tested for C++11.
>
> It would be appropriate to only test C++2a if you were adding
> exception specifications that only applied for C++2a, like so:
>
>         constexpr tuple(_UElements&&... __elements)
> #if __cplusplus > 201703L
>         noexcept(__and_<is_nothrow_constructible<_Elements,_UElements&&>...>::value)
> #endif
>
> But that's not what your patch does (and not what we want it to do).
>
> So I really think we need *some* tests that can run in C++11 mode.
> They wouldn't have to be as extensive and thorough as the ones you've
> provided, but if we make changes that affect C++11/14/17 then we
> should test those changes.
Ok, I now have a set of tests for c++11/14 and a set for C++17/20.

>
> >std::is_nothrow_convertible so I could do away with my copy conversion
> >helper functions.
> >Extending the tests to earlier standards would mean having two sets of
> >test expectations (one for pre C++17 copy conversion semantics, and
> >one for C++17 onwards). Would you like me to do that ?
>
> Can you show an example of the different semantics? What behaves
> differently in C++14?
>
> If the library provided a std::__is_nothrow_convertible trait for
> C++11 (with the same implementation as C++20's
> std::is_nothrow_convertible) and your tests used that, which test
> expectations would be affected?

Copy initialization pre C++17 involved creating a temporary of
destination type and then copying/moving the temporary to the result.
This means that a hypothetical std::__is_nothrow_convertible
implementation pre C++17 involves an additional call to a copy/move
constructor and that in some cases changes the nothrow outcome.

Here is an example of such a case :
https://wandbox.org/permlink/PppTzLXrZH2Dk4eo

It will give different result for C++11/14 and C++17/20

The new diff containing changes addressing review comments is attached
to this e-mail.

Let me know what you think,
Nina

>

[-- Attachment #2: noexcept_tuple_v2.diff --]
[-- Type: application/octet-stream, Size: 102050 bytes --]

Index: libstdc++-v3/include/std/tuple
===================================================================
--- libstdc++-v3/include/std/tuple	(revision 268955)
+++ libstdc++-v3/include/std/tuple	(working copy)
@@ -552,6 +552,12 @@
 	  return
 	    __and_<is_nothrow_assignable<_Elements&, _UElements>...>::value;
 	}
+      template<typename... _UElements>
+	static constexpr bool __nothrow_constructible()
+	{
+	  return
+	    __and_<is_nothrow_constructible<_Elements, _UElements>...>::value;
+	}
 
     public:
       template<typename _Dummy = void,
@@ -559,6 +565,7 @@
                                     _ImplicitlyDefaultConstructibleTuple(),
                                   bool>::type = true>
       constexpr tuple()
+      noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
       : _Inherited() { }
 
       template<typename _Dummy = void,
@@ -569,6 +576,7 @@
                                     _ImplicitlyDefaultConstructibleTuple(),
                                   bool>::type = false>
       explicit constexpr tuple()
+      noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
       : _Inherited() { }
 
       // Shortcut for the cases where constructors taking _Elements...
@@ -586,6 +594,7 @@
                  && (sizeof...(_Elements) >= 1),
                bool>::type=true>
         constexpr tuple(const _Elements&... __elements)
+        noexcept(__nothrow_constructible<const _Elements&...>())
       : _Inherited(__elements...) { }
 
       template<typename _Dummy = void,
@@ -597,6 +606,7 @@
                  && (sizeof...(_Elements) >= 1),
                bool>::type=false>
       explicit constexpr tuple(const _Elements&... __elements)
+      noexcept(__nothrow_constructible<const _Elements&...>())
       : _Inherited(__elements...) { }
 
       // Shortcut for the cases where constructors taking _UElements...
@@ -624,6 +634,7 @@
                   && (sizeof...(_Elements) >= 1),
         bool>::type=true>
         constexpr tuple(_UElements&&... __elements)
+        noexcept(__nothrow_constructible<_UElements...>())
         : _Inherited(std::forward<_UElements>(__elements)...) { }
 
       template<typename... _UElements, typename
@@ -635,6 +646,7 @@
                   && (sizeof...(_Elements) >= 1),
         bool>::type=false>
         explicit constexpr tuple(_UElements&&... __elements)
+        noexcept(__nothrow_constructible<_UElements...>())
 	: _Inherited(std::forward<_UElements>(__elements)...) {	}
 
       constexpr tuple(const tuple&) = default;
@@ -656,6 +668,7 @@
                     _NonNestedTuple<const tuple<_UElements...>&>(),
         bool>::type=true>
         constexpr tuple(const tuple<_UElements...>& __in)
+        noexcept(__nothrow_constructible<const _UElements&...>())
         : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
         { }
 
@@ -667,7 +680,8 @@
                   && _TNTC<_Dummy>::template
                     _NonNestedTuple<const tuple<_UElements...>&>(),
         bool>::type=false>
-        explicit constexpr tuple(const tuple<_UElements...>& __in)
+        explicit constexpr tuple(const tuple<_UElements...>& __in)        
+        noexcept(__nothrow_constructible<const _UElements&...>())
         : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
         { }
 
@@ -680,6 +694,7 @@
                     _NonNestedTuple<tuple<_UElements...>&&>(),
         bool>::type=true>
         constexpr tuple(tuple<_UElements...>&& __in)
+        noexcept(__nothrow_constructible<_UElements...>())
         : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
 
       template<typename... _UElements, typename _Dummy = void, typename
@@ -691,6 +706,7 @@
                     _NonNestedTuple<tuple<_UElements...>&&>(),
         bool>::type=false>
         explicit constexpr tuple(tuple<_UElements...>&& __in)
+        noexcept(__nothrow_constructible<_UElements...>())
         : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
 
       // Allocator-extended constructors.
@@ -908,6 +924,13 @@
 			is_nothrow_assignable<_T2&, _U2>>::value;
 	}
 
+      template<typename _U1, typename _U2>
+    static constexpr bool __nothrow_constructible()
+    {
+      return __and_<is_nothrow_constructible<_T1, _U1>,
+    		is_nothrow_constructible<_T2, _U2>>::value;
+    }
+
     public:
       template <typename _U1 = _T1,
                 typename _U2 = _T2,
@@ -916,6 +939,8 @@
                                      __is_implicitly_default_constructible<_U2>>
                                    ::value, bool>::type = true>
 	constexpr tuple()
+	noexcept(__and_<is_nothrow_default_constructible<_T1>,
+   			is_nothrow_default_constructible<_T2>>::value)
 	: _Inherited() { }
 
       template <typename _U1 = _T1,
@@ -929,6 +954,8 @@
                              __is_implicitly_default_constructible<_U2>>>>
                   ::value, bool>::type = false>
 	explicit constexpr tuple()
+	noexcept(__and_<is_nothrow_default_constructible<_T1>,
+ 			is_nothrow_default_constructible<_T2>>::value)
 	: _Inherited() { }
 
       // Shortcut for the cases where constructors taking _T1, _T2
@@ -943,6 +970,7 @@
                            _ImplicitlyConvertibleTuple<_T1, _T2>(),
 	bool>::type = true>
         constexpr tuple(const _T1& __a1, const _T2& __a2)
+        noexcept(__nothrow_constructible<const _T1&, const _T2&>())
         : _Inherited(__a1, __a2) { }
 
       template<typename _Dummy = void, typename
@@ -952,6 +980,7 @@
                            _ImplicitlyConvertibleTuple<_T1, _T2>(),
 	bool>::type = false>
         explicit constexpr tuple(const _T1& __a1, const _T2& __a2)
+        noexcept(__nothrow_constructible<const _T1&, const _T2&>())
         : _Inherited(__a1, __a2) { }
 
       // Shortcut for the cases where constructors taking _U1, _U2
@@ -966,6 +995,7 @@
 	          && !is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value,
 	bool>::type = true>
         constexpr tuple(_U1&& __a1, _U2&& __a2)
+        noexcept(__nothrow_constructible<_U1, _U2>())
 	: _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
 
       template<typename _U1, typename _U2, typename
@@ -976,6 +1006,7 @@
 	          && !is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value,
 	bool>::type = false>
         explicit constexpr tuple(_U1&& __a1, _U2&& __a2)
+        noexcept(__nothrow_constructible<_U1, _U2>())
 	: _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
 
       constexpr tuple(const tuple&) = default;
@@ -989,6 +1020,7 @@
                     _ImplicitlyConvertibleTuple<_U1, _U2>(),
 	bool>::type = true>
         constexpr tuple(const tuple<_U1, _U2>& __in)
+        noexcept(__nothrow_constructible<const _U1&, const _U2&>())
 	: _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
 
       template<typename _U1, typename _U2, typename
@@ -998,6 +1030,7 @@
                     _ImplicitlyConvertibleTuple<_U1, _U2>(),
 	bool>::type = false>
         explicit constexpr tuple(const tuple<_U1, _U2>& __in)
+        noexcept(__nothrow_constructible<const _U1&, const _U2&>())
 	: _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
 
       template<typename _U1, typename _U2, typename
@@ -1007,6 +1040,7 @@
                     _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
 	bool>::type = true>
         constexpr tuple(tuple<_U1, _U2>&& __in)
+        noexcept(__nothrow_constructible<_U1, _U2>())
 	: _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
 
       template<typename _U1, typename _U2, typename
@@ -1016,6 +1050,7 @@
                     _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
 	bool>::type = false>
         explicit constexpr tuple(tuple<_U1, _U2>&& __in)
+        noexcept(__nothrow_constructible<_U1, _U2>())
 	: _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
 
       template<typename _U1, typename _U2, typename
@@ -1025,6 +1060,7 @@
                     _ImplicitlyConvertibleTuple<_U1, _U2>(),
 	bool>::type = true>
         constexpr tuple(const pair<_U1, _U2>& __in)
+        noexcept(__nothrow_constructible<const _U1&, const _U2&>())
 	: _Inherited(__in.first, __in.second) { }
 
       template<typename _U1, typename _U2, typename
@@ -1034,6 +1070,7 @@
                     _ImplicitlyConvertibleTuple<_U1, _U2>(),
 	bool>::type = false>
         explicit constexpr tuple(const pair<_U1, _U2>& __in)
+        noexcept(__nothrow_constructible<const _U1&, const _U2&>())
 	: _Inherited(__in.first, __in.second) { }
 
       template<typename _U1, typename _U2, typename
@@ -1043,6 +1080,7 @@
                     _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
 	bool>::type = true>
         constexpr tuple(pair<_U1, _U2>&& __in)
+        noexcept(__nothrow_constructible<_U1, _U2>())
 	: _Inherited(std::forward<_U1>(__in.first),
 		     std::forward<_U2>(__in.second)) { }
 
@@ -1053,6 +1091,7 @@
                     _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
 	bool>::type = false>
         explicit constexpr tuple(pair<_U1, _U2>&& __in)
+        noexcept(__nothrow_constructible<_U1, _U2>())
 	: _Inherited(std::forward<_U1>(__in.first),
 		     std::forward<_U2>(__in.second)) { }
 
Index: libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc
===================================================================
--- libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc	(nonexistent)
+++ libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc	(working copy)
@@ -0,0 +1,950 @@
+//{ dg-do run { target { c++11_only || c++14_only } } }
+
+// 2019-04-10  Nina Dinka Ranns  <dinka.ranns@gmail.com>
+//
+// Copyright (C) 2019 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>
+#include <testsuite_tr1.h>
+#include <utility>
+
+/* DefaultConstructionTests */
+
+using namespace __gnu_test;
+
+bool throwing_ctor_called = false;
+
+namespace test_trait{
+   template <bool B>
+   using bool_constant = std::integral_constant<bool, B>;
+
+   template<typename _From, typename _To,
+           bool = std::__or_<std::is_void<_From>, std::is_function<_To>,
+		   std::is_array<_To>>::value>
+    struct __is_nt_convertible_helper
+    : std::is_void<_To>
+    { };
+
+  template<typename _From, typename _To>
+    class __is_nt_convertible_helper<_From, _To, false>
+    {
+      template<typename _To1>
+	static void __test_aux(_To1) noexcept;
+
+      template<typename _From1, typename _To1>
+	static bool_constant<noexcept(__test_aux<_To1>(std::declval<_From1>()))>
+	__test(int);
+
+      template<typename, typename>
+	static std::false_type
+	__test(...);
+
+    public:
+      using type = decltype(__test<_From, _To>(0));
+    };
+
+  /// is_nothrow_convertible
+  template<typename _From, typename _To>
+    struct is_nothrow_convertible
+    : public __is_nt_convertible_helper<_From, _To>::type
+    { };
+
+  /// is_nothrow_convertible_v
+  template<typename _From, typename _To>
+    constexpr bool is_nothrow_convertible_v
+      = is_nothrow_convertible<_From, _To>::value;
+}
+
+template<typename T>
+bool  checkDefaultThrowConstruct()
+{
+  throwing_ctor_called = false;
+  bool deduced_nothrow = std::is_nothrow_constructible<T>::value;
+  T t{};
+  return throwing_ctor_called != deduced_nothrow;
+}
+template<typename T, typename U>
+bool  checkCopyThrowConstruct()
+{
+  throwing_ctor_called = false;
+  bool deduced_nothrow = std::is_nothrow_constructible<T, U&>::value;
+  U u;
+  T t{u};
+  return throwing_ctor_called != deduced_nothrow;
+}
+template<typename T, typename U>
+bool  checkMoveThrowConstruct()
+{
+  throwing_ctor_called = false;
+  bool deduced_nothrow = std::is_nothrow_constructible<T, U&&>::value;
+  U u;
+  T t{std::move(u)};
+  return throwing_ctor_called != deduced_nothrow;
+}
+
+typedef std::tuple<int> IT;
+typedef std::tuple<const int> CIT;
+typedef std::tuple<int&&> RVIT;
+typedef std::tuple<int, int> IIT;
+typedef std::pair<int, int> IIP;
+typedef std::tuple<int, int, int> IIIT;
+
+namespace DefaultConstructionTests
+{
+  struct NoexceptDC
+  {
+    NoexceptDC() noexcept(true){}
+  };
+
+  struct ExceptDC
+  {
+    ExceptDC() noexcept(false)
+      {  throwing_ctor_called = true; }
+  };
+
+  struct ExplicitNoexceptDC
+  {
+    explicit ExplicitNoexceptDC() noexcept(true)
+        {}
+  };
+
+  struct ExplicitExceptDC
+  {
+    explicit ExplicitExceptDC() noexcept(false)
+        {  throwing_ctor_called = true; }
+  };
+
+  typedef std::tuple<NoexceptDC> NDT;
+  typedef std::tuple<ExceptDC> EDT;
+  typedef std::tuple<ExplicitNoexceptDC> X_NDT;
+  typedef std::tuple<ExplicitExceptDC> X_EDT;
+
+  typedef std::tuple<NoexceptDC,NoexceptDC> NNDT;
+  typedef std::tuple<ExceptDC,ExceptDC> EEDT;
+  typedef std::tuple<ExceptDC,NoexceptDC> ENDT;
+  typedef std::tuple<ExplicitNoexceptDC,NoexceptDC> X_NNDT;
+  typedef std::tuple<ExplicitExceptDC,ExceptDC> X_EEDT;
+  typedef std::tuple<ExceptDC,ExplicitNoexceptDC> X_ENDT;
+
+  typedef std::tuple<long, NoexceptDC, NoexceptDC> LNDNDT;
+  typedef std::tuple<long, NoexceptDC, ExceptDC> LNDEDT;
+  typedef std::tuple<long, ExplicitNoexceptDC, NoexceptDC> X_LNEDNDT;
+  typedef std::tuple<long, ExplicitNoexceptDC, ExceptDC> X_LNEDEDT;
+  typedef std::tuple<long, ExplicitExceptDC, ExceptDC> X_LEEDEDT;
+
+
+  /* if it has E in the name, it contains a type that throws when default constructed */
+  static_assert(std::is_nothrow_constructible<IT>::value, "");
+  static_assert(std::is_nothrow_constructible<NDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<EDT>::value, "");
+  static_assert(std::is_nothrow_constructible<X_NDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<X_EDT>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IIT>::value, "");
+  static_assert(std::is_nothrow_constructible<NNDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<EEDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<ENDT>::value, "");
+  static_assert(std::is_nothrow_constructible<X_NNDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<X_EEDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<X_ENDT>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IIIT>::value, "");
+  static_assert(std::is_nothrow_constructible<LNDNDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<LNDEDT>::value, "");
+  static_assert(std::is_nothrow_constructible<X_LNEDNDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<X_LNEDEDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<X_LEEDEDT>::value, "");
+
+  void Run()
+  {
+    VERIFY( checkDefaultThrowConstruct<IT>() );
+    VERIFY( checkDefaultThrowConstruct<NDT>() );
+    VERIFY( checkDefaultThrowConstruct<EDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_NDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_EDT>() );
+
+    VERIFY( checkDefaultThrowConstruct<IIT>() );
+    VERIFY( checkDefaultThrowConstruct<NNDT>() );
+    VERIFY( checkDefaultThrowConstruct<EEDT>() );
+    VERIFY( checkDefaultThrowConstruct<ENDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_NNDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_EEDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_ENDT>() );
+
+    VERIFY( checkDefaultThrowConstruct<IIIT>() );
+    VERIFY( checkDefaultThrowConstruct<LNDNDT>() );
+    VERIFY( checkDefaultThrowConstruct<LNDEDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_LNEDNDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_LNEDEDT>() );
+  }
+}
+namespace AllNoThrow
+{
+  static_assert(std::is_nothrow_constructible<IT, int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IT, const int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IT, int&&>::value, "");
+  static_assert(std::is_nothrow_constructible<IT, const int&&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IT, IT>::value, "");
+  static_assert(std::is_nothrow_constructible<IT, const IT &>::value, "");
+  static_assert(std::is_nothrow_constructible<IT, CIT>::value, "");
+
+  static_assert(test_trait::is_nothrow_convertible<int&, IT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<const int&, IT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<int&&, IT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<const int&&, IT>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IIT, int&, int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIT, const int&, const int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIT, int&&, int&&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIT, const int&&, const int&&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IIT, IIT>::value, "");
+  static_assert(std::is_nothrow_constructible<IIT, const IIT &>::value, "");
+  static_assert(std::is_nothrow_constructible<IIT, IIP>::value, "");
+  static_assert(std::is_nothrow_constructible<IIT, const IIP>::value, "");
+
+  static_assert(test_trait::is_nothrow_convertible<IIT, IIT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<const IIT &, IIT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<IIP, IIT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<const IIP, IIT>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IIIT, IIIT&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIIT, const IIIT &>::value, "");
+  static_assert(std::is_nothrow_constructible<IIIT, IIIT&&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIIT, const IIIT&&>::value, "");
+
+  static_assert(test_trait::is_nothrow_convertible<IIIT&, IIIT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<const IIIT &, IIIT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<IIIT&&, IIIT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<const IIIT&&, IIIT>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IIIT, int&, int&, int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIIT, const int&, const int&, int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIIT, int&&, int&&, int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIIT, const int&&, const int&&, int&>::value, "");
+}
+namespace ThrowCopyNothrowConversion
+{
+  struct A
+  {
+    A() noexcept(true)
+        {}
+
+    A(const int&) noexcept(true)
+      {}
+
+    A(const A&) noexcept(false)
+      {  throwing_ctor_called = true; }
+
+  };
+
+  typedef std::tuple<A> AT;
+  typedef std::tuple<A,A> AAT;
+  typedef std::pair<A,A> AAP;
+  typedef std::tuple<int,A> IAT;
+  typedef std::pair<int,A> IAP;
+  typedef std::tuple<A,A,A> AAAT;
+  typedef std::tuple<int,int,A> IIAT;
+
+/* one element tests */
+  static_assert(std::is_nothrow_constructible<AT,int>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,const int>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,int&>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,const int &>::value,"");
+
+  static_assert(std::is_nothrow_constructible<AT,IT>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,const IT>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,IT&>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,const IT &>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,std::tuple<int&>>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,const std::tuple<int&&>>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<int,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const int,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<int&,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const int &,AT>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<IT,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IT,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IT&,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IT &,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<std::tuple<int&>,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const std::tuple<int&&>,AT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<AT,A>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,const A>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,A&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,const A &>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<AT,AT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,const AT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,AT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,const AT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,std::tuple<A&>>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,const std::tuple<A&&>>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<A,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const A,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<A&,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const A &,AT>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<AT,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const AT,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<AT&,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const AT &,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<std::tuple<A&>,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const std::tuple<A&&>,AT>::value,"");
+
+/* two element tests */
+
+  static_assert(std::is_nothrow_constructible<AAT,IIT>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,const IIT>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,IIT&>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,const IIT &>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,IIP>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,const IIP>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,IIP&>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,const IIP &>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,std::tuple<int&,int&>>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<IIT,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIT,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IIT&,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIT &,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IIP,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIP,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IIP&,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIP &,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<std::tuple<int&,int&>,AAT>::value,"");
+
+
+  static_assert(!std::is_nothrow_constructible<AAT,AAT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const AAT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,AAT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const AAT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,AAP>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const AAP>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,AAP&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const AAP &>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,std::tuple<A&,A&>>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<AAT,IAT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const IAT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,IAT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const IAT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,IAP>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const IAP>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,IAP&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const IAP &>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,std::tuple<A&,int&>>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<AAT,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const AAT,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<AAT&,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const AAT &,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<AAP,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const AAP,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<AAP&,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const AAP &,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<std::tuple<A&,A&>,AAT>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<IAT,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IAT,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IAT&,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IAT &,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IAP,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IAP,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IAP&,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IAP &,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<std::tuple<A&,int&>,AAT>::value,"");
+
+
+  static_assert(std::is_nothrow_constructible<AAT,int&,const int&>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,int&&,const int&&>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<AAT,A&,const A&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,A&&,const A&&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const A &&,const int&&>::value,"");
+
+/* three element tests */
+  static_assert(std::is_nothrow_constructible<AAAT,IIIT>::value,"");
+  static_assert(std::is_nothrow_constructible<AAAT,const IIIT>::value,"");
+  static_assert(std::is_nothrow_constructible<AAAT,IIIT&>::value,"");
+  static_assert(std::is_nothrow_constructible<AAAT,const IIIT &>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<IIIT,AAAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIIT,AAAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IIIT&,AAAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIIT &,AAAT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<AAAT,IIAT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAAT,const IIAT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAAT,IIAT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAAT,const IIAT &>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<IIAT,AAAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIAT,AAAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IIAT&,AAAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIAT &,AAAT>::value,"");
+
+  static_assert(std::is_nothrow_constructible<AAAT,int&,const int&,int&&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAAT,int &,const A &&,const int&&>::value,"");
+
+  void Run()
+  {
+    VERIFY( (checkCopyThrowConstruct<AT,int>()) );
+    VERIFY( (checkMoveThrowConstruct<AT,int>()) );
+    VERIFY( (checkCopyThrowConstruct<AT,A>()) );
+    VERIFY( (checkMoveThrowConstruct<AT,A>()) );
+    VERIFY( (checkCopyThrowConstruct<AT,AT>()) );
+    VERIFY( (checkMoveThrowConstruct<AT,AT>()) );
+    VERIFY( (checkCopyThrowConstruct<AT,IT>()) );
+    VERIFY( (checkMoveThrowConstruct<AT,IT>()) );
+    VERIFY( (checkMoveThrowConstruct<AT,CIT>()) );
+    VERIFY( (checkCopyThrowConstruct<AAT,AAT>()) );
+    VERIFY( (checkMoveThrowConstruct<AAT,AAT>()) );
+    VERIFY( (checkCopyThrowConstruct<AAT,IIT>()) );
+    VERIFY( (checkMoveThrowConstruct<AAT,IIT>()) );
+    VERIFY( (checkCopyThrowConstruct<AAT,IIP>()) );
+    VERIFY( (checkMoveThrowConstruct<AAT,IIP>()) );
+
+    VERIFY( (checkCopyThrowConstruct<AAT,std::tuple<int,A>>()) );
+    VERIFY( (checkMoveThrowConstruct<AAT,std::tuple<int,A>>()) );
+    VERIFY( (checkCopyThrowConstruct<AAT,std::pair<int,A>>()) );
+    VERIFY( (checkMoveThrowConstruct<AAT,std::pair<int,A>>()) );
+
+    VERIFY( (checkCopyThrowConstruct<AAAT,AAAT>()) );
+    VERIFY( (checkMoveThrowConstruct<AAAT,AAAT>()) );
+    VERIFY( (checkCopyThrowConstruct<AAAT,IIAT>()) );
+    VERIFY( (checkMoveThrowConstruct<AAAT,IIAT>()) );
+  }
+}
+namespace NothrowCopyThrowMoveThrowCopyConversionNothrowMoveConversion
+{
+  struct B
+  {
+    B() noexcept(true)
+        {}
+
+    B(const int&) noexcept(false)
+      {  throwing_ctor_called = true; }
+
+    B(int&&) noexcept(true)
+      {}
+
+    B(const B&) noexcept(true)
+      {}
+
+    B(B&&) noexcept(false)
+      {  throwing_ctor_called = true; }
+  };
+
+
+  struct D
+  {
+    D() noexcept(true)
+        {}
+
+    explicit
+    D(const int&) noexcept(false)
+    {  throwing_ctor_called = true; }
+
+    explicit
+    D(int&&) noexcept(true)
+        {}
+
+    explicit
+    D(const D&) noexcept(true)
+      {}
+
+    explicit
+    D(D&&) noexcept(false)
+    {  throwing_ctor_called = true; }
+
+  };
+
+  typedef std::tuple<B> BT;
+  typedef std::tuple<B,B> BBT;
+  typedef std::pair<B,B> BBP;
+  typedef std::tuple<D> DT;
+  typedef std::tuple<D,D> DDT;
+  typedef std::pair<D,D> DDP;
+  typedef std::tuple<int,D> IDT;
+  typedef std::pair<int,D> IDP;
+  typedef std::tuple<int,B> IBT;
+  typedef std::pair<int,B> IBP;
+  typedef std::tuple<D,B> DBT;
+  typedef std::pair<D,B> DBP;
+  typedef std::tuple<B,B,B> BBBT;
+  typedef std::tuple<D,D,D> DDDT;
+  typedef std::tuple<int,D,int> IDIT;
+  typedef std::tuple<int,B,int> IBIT;
+  typedef std::tuple<int,D,B> IDBT;
+
+/* one element tests */
+  static_assert(std::is_nothrow_constructible<BT, int>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, const int>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, int&>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, const int &>::value, "");
+
+  static_assert(std::is_nothrow_constructible<BT, IT>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT,const IT>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, IT&>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, const IT &>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, std::tuple<int&>>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, const std::tuple<int&&>>::value, "");
+
+  static_assert(!test_trait::is_nothrow_convertible<int,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const int,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<int&,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const int &,BT>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<IT,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IT,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IT&,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IT &,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<std::tuple<int&>,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const std::tuple<int&&>,BT>::value,"");
+
+
+  static_assert(!std::is_nothrow_constructible<BT, B>::value, "");
+  static_assert(std::is_nothrow_constructible<BT,const B>::value, "");
+  static_assert(std::is_nothrow_constructible<BT, B&>::value, "");
+  static_assert(std::is_nothrow_constructible<BT, const B &>::value, "");
+
+  static_assert(!std::is_nothrow_constructible<BT, BT>::value, "");
+  static_assert(std::is_nothrow_constructible<BT,const BT>::value, "");
+  static_assert(std::is_nothrow_constructible<BT, BT&>::value, "");
+  static_assert(std::is_nothrow_constructible<BT, const BT &>::value, "");
+  static_assert(std::is_nothrow_constructible<BT, std::tuple<B&>>::value, "");
+  static_assert(std::is_nothrow_constructible<BT, const std::tuple<B&&>>::value, "");
+
+  static_assert(!test_trait::is_nothrow_convertible<B,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const B,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<B&,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const B &,BT>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<BT,BT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const BT,BT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<BT&,BT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const BT &,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<std::tuple<B&>,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const std::tuple<B&&>,BT>::value,"");
+
+/* explicit */
+  static_assert(std::is_nothrow_constructible<DT, int>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, const int>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, int&>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, const int &>::value, "");
+
+  static_assert(std::is_nothrow_constructible<DT, IT>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT,const IT>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, IT&>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, const IT &>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, std::tuple<int&>>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, const std::tuple<int&&>>::value, "");
+
+  static_assert(!std::is_nothrow_constructible<DT, D>::value, "");
+  static_assert(std::is_nothrow_constructible<DT,const D>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, D&>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const D &>::value, "");
+
+  static_assert(!std::is_nothrow_constructible<DT, DT>::value, "");
+  static_assert(std::is_nothrow_constructible<DT,const DT>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, DT&>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const DT &>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, std::tuple<D&>>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const std::tuple<D&&>>::value, "");
+
+  static_assert(!test_trait::is_nothrow_convertible<DT,DT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const DT,DT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<DT&,DT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const DT &,DT>::value,"");
+
+/* two elements tests */
+  static_assert(std::is_nothrow_constructible<BBT,IIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,IIT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IIT &>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,IIP>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IIP>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,IIP&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IIP &>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,std::tuple<int&,int&>>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<IIT,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIT,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IIT&,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIT &,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IIP,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIP,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IIP&,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIP &,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<std::tuple<int&,int&>,BBT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<BBT,BBT>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,const BBT>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,BBT&>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,const BBT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,BBP>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,const BBP>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,BBP&>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,const BBP &>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,std::tuple<B&,B&>>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<BBT,IBT>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IBT>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,IBT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IBT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,IBP>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IBP>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,IBP&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IBP &>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,std::tuple<const B&,int&&>>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<BBT,BBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const BBT,BBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<BBT&,BBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const BBT &,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<BBP,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const BBP,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<BBP&,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const BBP &,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<std::tuple<B&,int&&>,BBT>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<IBT,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IBT,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IBT&,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IBT &,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IBP,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IBP,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IBP&,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IBP &,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<std::tuple<B&,int&>,BBT>::value,"");
+
+
+  static_assert(!std::is_nothrow_constructible<BBT,int&,const int&>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,int&&,const B&>::value,"");
+
+  static_assert(std::is_nothrow_constructible<BBT,B&,const B&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,B&&,const B&&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const B &&,const int&&>::value,"");
+
+/* explicit */
+  static_assert(std::is_nothrow_constructible<DDT,IIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,IIT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IIT &>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,IIP>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IIP>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,IIP&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IIP &>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,std::tuple<int&,int&>>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<DDT,DDT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const DDT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,DDT&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const DDT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,DDP>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const DDP>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,DDP&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const DDP &>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,std::tuple<D&,D&>>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<DDT,IDT>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IDT>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,IDT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IDT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,IDP>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IDP>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,IDP&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IDP &>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,std::tuple<const D&,int&&>>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<DDT,DDT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const DDT,DDT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<DDT&,DDT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const DDT &,DDT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<DDT,int&,const int&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,int&&,const D&>::value,"");
+
+  static_assert(std::is_nothrow_constructible<DDT,D&,const D&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,D&&,const D&&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const D &&,const int&&>::value,"");
+
+/* three elements tests */
+  static_assert(std::is_nothrow_constructible<BBBT,IIIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBBT,const IIIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBBT,IIIT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBBT,const IIIT &>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<IIIT,BBBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIIT,BBBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IIIT&,BBBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIIT &,BBBT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<BBBT,BBBT>::value,"");
+  static_assert(std::is_nothrow_constructible<BBBT,const BBBT>::value,"");
+  static_assert(std::is_nothrow_constructible<BBBT,BBBT&>::value,"");
+  static_assert(std::is_nothrow_constructible<BBBT,const BBBT &>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<BBBT,BBBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const BBBT,BBBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<BBBT&,BBBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const BBBT &,BBBT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<BBBT,int&,const int&,int&&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBBT,int&, B&&,const int&&>::value,"");
+  static_assert(std::is_nothrow_constructible<BBBT,int&&, B&,const B&&>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<BBBT,std::tuple<int&,const int&,int&&>>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBBT,std::tuple<int &, B&&,const int&&>>::value,"");
+  static_assert(std::is_nothrow_constructible<BBBT,std::tuple<int &&, B&,const B&&>>::value,"");
+
+/* explicit */
+  static_assert(std::is_nothrow_constructible<DDDT,IIIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDDT,const IIIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDDT,IIIT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDDT,const IIIT &>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<DDDT,DDDT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDDT,const DDDT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDDT,DDDT&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDDT,const DDDT &>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<DDDT,DDDT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const DDDT,DDDT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<DDDT&,DDDT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const DDDT &,DDDT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<DDDT,int&,const int&,int&&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDDT,int &, D&&,const int&&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDDT,int &&, D&,const D&&>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<DDDT,std::tuple<int&,const int&,int&&>>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDDT,std::tuple<int &, D&&,const int&&>>::value,"");
+  static_assert(std::is_nothrow_constructible<DDDT,std::tuple<int &&, D&,const D&&>>::value,"");
+
+
+  void Run()
+  {
+    VERIFY( (checkCopyThrowConstruct<BT, int>()) );
+    VERIFY( (checkMoveThrowConstruct<BT, int>()) );
+    VERIFY( (checkCopyThrowConstruct<BT, B>()) );
+    VERIFY( (checkMoveThrowConstruct<BT, B>()) );
+    VERIFY( (checkCopyThrowConstruct<BT, IT>()) );
+    VERIFY( (checkMoveThrowConstruct<BT, IT>()) );
+    VERIFY( (checkMoveThrowConstruct<BT, CIT>()) );
+    VERIFY( (checkCopyThrowConstruct<BBT, IIT>()) );
+    VERIFY( (checkMoveThrowConstruct<BBT, IIT>()) );
+    VERIFY( (checkCopyThrowConstruct<BBT, IIP>()) );
+    VERIFY( (checkMoveThrowConstruct<BBT, IIP>()) );
+    VERIFY( (checkCopyThrowConstruct<BBT, BBP>()) );
+    VERIFY( (checkMoveThrowConstruct<BBT, BBP>()) );
+    VERIFY( (checkCopyThrowConstruct<BBT, std::tuple<B, int>>()) );
+    VERIFY( (checkMoveThrowConstruct<BBT, std::tuple<B, int>>()) );
+
+    VERIFY( (checkCopyThrowConstruct<DT, int>()) );
+    VERIFY( (checkMoveThrowConstruct<DT, int>()) );
+    VERIFY( (checkCopyThrowConstruct<DT, D>()) );
+    VERIFY( (checkMoveThrowConstruct<DT, D>()) );
+    VERIFY( (checkCopyThrowConstruct<DT, IT>()) );
+    VERIFY( (checkMoveThrowConstruct<DT, IT>()) );
+    VERIFY( (checkMoveThrowConstruct<DT, CIT>()) );
+    VERIFY( (checkCopyThrowConstruct<DDT, IIT>()) );
+    VERIFY( (checkMoveThrowConstruct<DDT, IIT>()) );
+    VERIFY( (checkCopyThrowConstruct<DDT, IIP>()) );
+    VERIFY( (checkMoveThrowConstruct<DDT, IIP>()) );
+    VERIFY( (checkCopyThrowConstruct<DDT, DDP>()) );
+    VERIFY( (checkMoveThrowConstruct<DDT, DDP>()) );
+    VERIFY( (checkCopyThrowConstruct<DDT, std::tuple<D, int>>()) );
+    VERIFY( (checkMoveThrowConstruct<DDT, std::tuple<D, int>>()) );
+
+    VERIFY( (checkCopyThrowConstruct<DBT, IIT>()) );
+    VERIFY( (checkMoveThrowConstruct<DBT, IIT>()) );
+    VERIFY( (checkCopyThrowConstruct<DBT, DBT>()) );
+    VERIFY( (checkMoveThrowConstruct<DBT, DBT>()) );
+    VERIFY( (checkCopyThrowConstruct<DBT, DBP>()) );
+    VERIFY( (checkMoveThrowConstruct<DBT, DBP>()) );
+    VERIFY( (checkCopyThrowConstruct<DBT, IIP>()) );
+    VERIFY( (checkMoveThrowConstruct<DBT, IIP>()) );
+
+
+    VERIFY( (checkCopyThrowConstruct<IDIT, IIIT>()) );
+    VERIFY( (checkMoveThrowConstruct<IDIT, IIIT>()) );
+    VERIFY( (checkCopyThrowConstruct<IDIT, IDIT>()) );
+    VERIFY( (checkMoveThrowConstruct<IDIT, IDIT>()) );
+    VERIFY( (checkCopyThrowConstruct<IBIT, IIIT>()) );
+    VERIFY( (checkMoveThrowConstruct<IBIT, IIIT>()) );
+    VERIFY( (checkCopyThrowConstruct<IBIT, IBIT>()) );
+    VERIFY( (checkMoveThrowConstruct<IBIT, IBIT>()) );
+    VERIFY( (checkCopyThrowConstruct<IDBT, IIIT>()) );
+    VERIFY( (checkMoveThrowConstruct<IDBT, IIIT>()) );
+    VERIFY( (checkCopyThrowConstruct<IDBT, IDBT>()) );
+    VERIFY( (checkMoveThrowConstruct<IDBT, IDBT>()) );
+
+  }
+}
+namespace ThrowCopy
+{
+  struct C
+  {
+    C() noexcept(true)
+       {}
+
+    explicit
+    C(const C&) noexcept(true) {}
+
+  };
+
+  typedef std::tuple<C> CT;
+  typedef std::tuple<C,C> CCT;
+  typedef std::pair<C,C> CCP;
+  typedef std::tuple<int,int,C> IICT;
+
+  static_assert(std::is_nothrow_constructible<CT, C&>::value, "");
+  static_assert(std::is_nothrow_constructible<CT, const C&>::value, "");
+  static_assert(std::is_nothrow_constructible<CT, C&&>::value, "");
+  static_assert(std::is_nothrow_constructible<CT, const C &&>::value, "");
+
+
+  static_assert(std::is_nothrow_constructible<CCT, C&, C&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, const C&, const C&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, C&&, C&&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, const C &&, const C &&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IICT, int, int, C&>::value, "");
+  static_assert(std::is_nothrow_constructible<IICT, int, int, const C&>::value, "");
+  static_assert(std::is_nothrow_constructible<IICT, int, int, C&&>::value, "");
+  static_assert(std::is_nothrow_constructible<IICT, int, int, const C &&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<CT, CT&>::value, "");
+  static_assert(std::is_nothrow_constructible<CT, const CT&>::value, "");
+  static_assert(std::is_nothrow_constructible<CT, CT&&>::value, "");
+  static_assert(std::is_nothrow_constructible<CT, const CT &&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<CCT, CCT&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, const CCT&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, CCT&&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, const CCT &&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<CCT, CCP&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, const CCP&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, CCP&&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, const CCP &&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IICT, IICT&>::value, "");
+  static_assert(std::is_nothrow_constructible<IICT, const IICT&>::value, "");
+  static_assert(std::is_nothrow_constructible<IICT, IICT&&>::value, "");
+  static_assert(std::is_nothrow_constructible<IICT, const IICT &&>::value, "");
+
+}
+namespace ThrowMoveNothrowConversion
+{
+  struct D
+  {
+  D() noexcept(true)
+  {}
+
+  explicit
+  D(const int&) noexcept(true)
+  {}
+
+  explicit
+  D(int&&) noexcept(false)
+  {  throwing_ctor_called = true; }
+
+  };
+
+  typedef std::tuple<D> DT;
+  typedef std::tuple<D,D> DDT;
+  typedef std::pair<D,D> DDP;
+  typedef std::tuple<int,D,int> IDIT;
+
+
+  static_assert(!std::is_nothrow_constructible<DT, int>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const int>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, int&>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const int &>::value, "");
+
+  static_assert(!std::is_nothrow_constructible<DT, IT>::value, "");
+  static_assert(std::is_nothrow_constructible<DT,const IT>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, IT&>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const IT &>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, std::tuple<int&>>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const std::tuple<int&&>>::value, "");
+
+  static_assert(test_trait::is_nothrow_convertible<DT,DT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<D,DT>::value,"");
+
+/* two elements tests */
+  static_assert(!std::is_nothrow_constructible<DDT,IIT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const IIT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,IIT&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const IIT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,IIP>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const IIP>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,IIP&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const IIP &>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,std::tuple<int&,int&>>::value,"");
+
+  static_assert(std::is_nothrow_constructible<DDT,DDT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,DDP>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,std::tuple<int&,D>>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,std::pair<D,int&&>>::value,"");
+
+  static_assert(std::is_convertible<DDT,DDT>::value,"");
+
+/* three elements tests */
+  static_assert(!std::is_nothrow_constructible<IDIT,IIIT>::value,"");
+  static_assert(std::is_nothrow_constructible<IDIT,const IIIT>::value,"");
+  static_assert(std::is_nothrow_constructible<IDIT,IIIT&>::value,"");
+  static_assert(std::is_nothrow_constructible<IDIT,const IIIT &>::value,"");
+
+  static_assert(test_trait::is_nothrow_convertible<IDIT,IDIT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<IDIT,IDIT>::value,"");
+
+  static_assert(std::is_nothrow_constructible<IDIT,int&,const int&,int&&>::value,"");
+  static_assert(std::is_nothrow_constructible<IDIT,int &, D&&,const int&&>::value,"");
+  static_assert(std::is_nothrow_constructible<IDIT,std::tuple<int&,const int&,int&&>>::value,"");
+  static_assert(!std::is_nothrow_constructible<IDIT,std::tuple<int &, int&&,const int&&>>::value,"");
+
+  void Run()
+  {
+    VERIFY( (checkCopyThrowConstruct<DDT, IIT>()) );
+    VERIFY( (checkMoveThrowConstruct<DDT, IIT>()) );
+    VERIFY( (checkCopyThrowConstruct<DDT, std::tuple<D, int>>()) );
+    VERIFY( (checkMoveThrowConstruct<DDT, std::tuple<D, int>>()) );
+  }
+}
+
+int main()
+{
+
+  DefaultConstructionTests::Run();
+
+  ThrowCopyNothrowConversion::Run();
+
+  NothrowCopyThrowMoveThrowCopyConversionNothrowMoveConversion::Run();
+
+  ThrowMoveNothrowConversion::Run();
+
+}
+
Index: libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs_cpp17.cc
===================================================================
--- libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs_cpp17.cc	(nonexistent)
+++ libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs_cpp17.cc	(working copy)
@@ -0,0 +1,951 @@
+//{ dg-options "-std=gnu++2a" }
+//{ dg-do run { target c++17 } }
+
+// 2019-04-10  Nina Dinka Ranns  <dinka.ranns@gmail.com>
+//
+// Copyright (C) 2019 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>
+#include <testsuite_tr1.h>
+#include <utility>
+
+/* DefaultConstructionTests */
+
+using namespace __gnu_test;
+
+bool throwing_ctor_called = false;
+
+namespace test_trait{
+   template <bool B>
+   using bool_constant = std::integral_constant<bool, B>;
+
+   template<typename _From, typename _To,
+           bool = std::__or_<std::is_void<_From>, std::is_function<_To>,
+		   std::is_array<_To>>::value>
+    struct __is_nt_convertible_helper
+    : std::is_void<_To>
+    { };
+
+  template<typename _From, typename _To>
+    class __is_nt_convertible_helper<_From, _To, false>
+    {
+      template<typename _To1>
+	static void __test_aux(_To1) noexcept;
+
+      template<typename _From1, typename _To1>
+	static bool_constant<noexcept(__test_aux<_To1>(std::declval<_From1>()))>
+	__test(int);
+
+      template<typename, typename>
+	static std::false_type
+	__test(...);
+
+    public:
+      using type = decltype(__test<_From, _To>(0));
+    };
+
+  /// is_nothrow_convertible
+  template<typename _From, typename _To>
+    struct is_nothrow_convertible
+    : public __is_nt_convertible_helper<_From, _To>::type
+    { };
+
+  /// is_nothrow_convertible_v
+  template<typename _From, typename _To>
+    inline constexpr bool is_nothrow_convertible_v
+      = is_nothrow_convertible<_From, _To>::value;
+}
+
+template<typename T>
+bool  checkDefaultThrowConstruct()
+{
+  throwing_ctor_called = false;
+  bool deduced_nothrow = std::is_nothrow_constructible<T>::value;
+  T t{};
+  return throwing_ctor_called != deduced_nothrow;
+}
+template<typename T, typename U>
+bool  checkCopyThrowConstruct()
+{
+  throwing_ctor_called = false;
+  bool deduced_nothrow = std::is_nothrow_constructible<T, U&>::value;
+  U u;
+  T t{u};
+  return throwing_ctor_called != deduced_nothrow;
+}
+template<typename T, typename U>
+bool  checkMoveThrowConstruct()
+{
+  throwing_ctor_called = false;
+  bool deduced_nothrow = std::is_nothrow_constructible<T, U&&>::value;
+  U u;
+  T t{std::move(u)};
+  return throwing_ctor_called != deduced_nothrow;
+}
+
+typedef std::tuple<int> IT;
+typedef std::tuple<const int> CIT;
+typedef std::tuple<int&&> RVIT;
+typedef std::tuple<int, int> IIT;
+typedef std::pair<int, int> IIP;
+typedef std::tuple<int, int, int> IIIT;
+
+namespace DefaultConstructionTests
+{
+  struct NoexceptDC
+  {
+    NoexceptDC() noexcept(true){}
+  };
+
+  struct ExceptDC
+  {
+    ExceptDC() noexcept(false)
+      {  throwing_ctor_called = true; }
+  };
+
+  struct ExplicitNoexceptDC
+  {
+    explicit ExplicitNoexceptDC() noexcept(true)
+        {}
+  };
+
+  struct ExplicitExceptDC
+  {
+    explicit ExplicitExceptDC() noexcept(false)
+        {  throwing_ctor_called = true; }
+  };
+
+  typedef std::tuple<NoexceptDC> NDT;
+  typedef std::tuple<ExceptDC> EDT;
+  typedef std::tuple<ExplicitNoexceptDC> X_NDT;
+  typedef std::tuple<ExplicitExceptDC> X_EDT;
+
+  typedef std::tuple<NoexceptDC,NoexceptDC> NNDT;
+  typedef std::tuple<ExceptDC,ExceptDC> EEDT;
+  typedef std::tuple<ExceptDC,NoexceptDC> ENDT;
+  typedef std::tuple<ExplicitNoexceptDC,NoexceptDC> X_NNDT;
+  typedef std::tuple<ExplicitExceptDC,ExceptDC> X_EEDT;
+  typedef std::tuple<ExceptDC,ExplicitNoexceptDC> X_ENDT;
+
+  typedef std::tuple<long, NoexceptDC, NoexceptDC> LNDNDT;
+  typedef std::tuple<long, NoexceptDC, ExceptDC> LNDEDT;
+  typedef std::tuple<long, ExplicitNoexceptDC, NoexceptDC> X_LNEDNDT;
+  typedef std::tuple<long, ExplicitNoexceptDC, ExceptDC> X_LNEDEDT;
+  typedef std::tuple<long, ExplicitExceptDC, ExceptDC> X_LEEDEDT;
+
+
+  /* if it has E in the name, it contains a type that throws when default constructed */
+  static_assert(std::is_nothrow_constructible<IT>::value, "");
+  static_assert(std::is_nothrow_constructible<NDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<EDT>::value, "");
+  static_assert(std::is_nothrow_constructible<X_NDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<X_EDT>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IIT>::value, "");
+  static_assert(std::is_nothrow_constructible<NNDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<EEDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<ENDT>::value, "");
+  static_assert(std::is_nothrow_constructible<X_NNDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<X_EEDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<X_ENDT>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IIIT>::value, "");
+  static_assert(std::is_nothrow_constructible<LNDNDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<LNDEDT>::value, "");
+  static_assert(std::is_nothrow_constructible<X_LNEDNDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<X_LNEDEDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<X_LEEDEDT>::value, "");
+
+  void Run()
+  {
+    VERIFY( checkDefaultThrowConstruct<IT>() );
+    VERIFY( checkDefaultThrowConstruct<NDT>() );
+    VERIFY( checkDefaultThrowConstruct<EDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_NDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_EDT>() );
+
+    VERIFY( checkDefaultThrowConstruct<IIT>() );
+    VERIFY( checkDefaultThrowConstruct<NNDT>() );
+    VERIFY( checkDefaultThrowConstruct<EEDT>() );
+    VERIFY( checkDefaultThrowConstruct<ENDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_NNDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_EEDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_ENDT>() );
+
+    VERIFY( checkDefaultThrowConstruct<IIIT>() );
+    VERIFY( checkDefaultThrowConstruct<LNDNDT>() );
+    VERIFY( checkDefaultThrowConstruct<LNDEDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_LNEDNDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_LNEDEDT>() );
+  }
+}
+namespace AllNoThrow
+{
+  static_assert(std::is_nothrow_constructible<IT, int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IT, const int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IT, int&&>::value, "");
+  static_assert(std::is_nothrow_constructible<IT, const int&&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IT, IT>::value, "");
+  static_assert(std::is_nothrow_constructible<IT, const IT &>::value, "");
+  static_assert(std::is_nothrow_constructible<IT, CIT>::value, "");
+
+  static_assert(test_trait::is_nothrow_convertible<int&, IT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<const int&, IT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<int&&, IT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<const int&&, IT>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IIT, int&, int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIT, const int&, const int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIT, int&&, int&&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIT, const int&&, const int&&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IIT, IIT>::value, "");
+  static_assert(std::is_nothrow_constructible<IIT, const IIT &>::value, "");
+  static_assert(std::is_nothrow_constructible<IIT, IIP>::value, "");
+  static_assert(std::is_nothrow_constructible<IIT, const IIP>::value, "");
+
+  static_assert(test_trait::is_nothrow_convertible<IIT, IIT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<const IIT &, IIT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<IIP, IIT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<const IIP, IIT>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IIIT, IIIT&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIIT, const IIIT &>::value, "");
+  static_assert(std::is_nothrow_constructible<IIIT, IIIT&&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIIT, const IIIT&&>::value, "");
+
+  static_assert(test_trait::is_nothrow_convertible<IIIT&, IIIT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<const IIIT &, IIIT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<IIIT&&, IIIT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<const IIIT&&, IIIT>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IIIT, int&, int&, int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIIT, const int&, const int&, int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIIT, int&&, int&&, int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIIT, const int&&, const int&&, int&>::value, "");
+}
+namespace ThrowCopyNothrowConversion
+{
+  struct A
+  {
+    A() noexcept(true)
+        {}
+
+    A(const int&) noexcept(true)
+      {}
+
+    A(const A&) noexcept(false)
+      {  throwing_ctor_called = true; }
+
+  };
+
+  typedef std::tuple<A> AT;
+  typedef std::tuple<A,A> AAT;
+  typedef std::pair<A,A> AAP;
+  typedef std::tuple<int,A> IAT;
+  typedef std::pair<int,A> IAP;
+  typedef std::tuple<A,A,A> AAAT;
+  typedef std::tuple<int,int,A> IIAT;
+
+/* one element tests */
+  static_assert(std::is_nothrow_constructible<AT,int>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,const int>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,int&>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,const int &>::value,"");
+
+  static_assert(std::is_nothrow_constructible<AT,IT>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,const IT>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,IT&>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,const IT &>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,std::tuple<int&>>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,const std::tuple<int&&>>::value,"");
+
+  static_assert(test_trait::is_nothrow_convertible<int,AT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const int,AT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<int&,AT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const int &,AT>::value,"");
+
+  static_assert(test_trait::is_nothrow_convertible<IT,AT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const IT,AT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<IT&,AT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const IT &,AT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<std::tuple<int&>,AT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const std::tuple<int&&>,AT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<AT,A>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,const A>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,A&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,const A &>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<AT,AT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,const AT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,AT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,const AT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,std::tuple<A&>>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,const std::tuple<A&&>>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<A,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const A,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<A&,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const A &,AT>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<AT,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const AT,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<AT&,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const AT &,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<std::tuple<A&>,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const std::tuple<A&&>,AT>::value,"");
+
+/* two element tests */
+
+  static_assert(std::is_nothrow_constructible<AAT,IIT>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,const IIT>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,IIT&>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,const IIT &>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,IIP>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,const IIP>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,IIP&>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,const IIP &>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,std::tuple<int&,int&>>::value,"");
+
+  static_assert(test_trait::is_nothrow_convertible<IIT,AAT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const IIT,AAT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<IIT&,AAT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const IIT &,AAT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<IIP,AAT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const IIP,AAT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<IIP&,AAT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const IIP &,AAT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<std::tuple<int&,int&>,AAT>::value,"");
+
+
+  static_assert(!std::is_nothrow_constructible<AAT,AAT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const AAT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,AAT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const AAT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,AAP>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const AAP>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,AAP&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const AAP &>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,std::tuple<A&,A&>>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<AAT,IAT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const IAT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,IAT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const IAT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,IAP>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const IAP>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,IAP&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const IAP &>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,std::tuple<A&,int&>>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<AAT,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const AAT,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<AAT&,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const AAT &,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<AAP,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const AAP,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<AAP&,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const AAP &,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<std::tuple<A&,A&>,AAT>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<IAT,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IAT,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IAT&,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IAT &,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IAP,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IAP,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IAP&,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IAP &,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<std::tuple<A&,int&>,AAT>::value,"");
+
+
+  static_assert(std::is_nothrow_constructible<AAT,int&,const int&>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,int&&,const int&&>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<AAT,A&,const A&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,A&&,const A&&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const A &&,const int&&>::value,"");
+
+/* three element tests */
+  static_assert(std::is_nothrow_constructible<AAAT,IIIT>::value,"");
+  static_assert(std::is_nothrow_constructible<AAAT,const IIIT>::value,"");
+  static_assert(std::is_nothrow_constructible<AAAT,IIIT&>::value,"");
+  static_assert(std::is_nothrow_constructible<AAAT,const IIIT &>::value,"");
+
+  static_assert(test_trait::is_nothrow_convertible<IIIT,AAAT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const IIIT,AAAT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<IIIT&,AAAT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const IIIT &,AAAT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<AAAT,IIAT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAAT,const IIAT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAAT,IIAT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAAT,const IIAT &>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<IIAT,AAAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIAT,AAAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IIAT&,AAAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIAT &,AAAT>::value,"");
+
+  static_assert(std::is_nothrow_constructible<AAAT,int&,const int&,int&&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAAT,int &,const A &&,const int&&>::value,"");
+
+  void Run()
+  {
+    VERIFY( (checkCopyThrowConstruct<AT,int>()) );
+    VERIFY( (checkMoveThrowConstruct<AT,int>()) );
+    VERIFY( (checkCopyThrowConstruct<AT,A>()) );
+    VERIFY( (checkMoveThrowConstruct<AT,A>()) );
+    VERIFY( (checkCopyThrowConstruct<AT,AT>()) );
+    VERIFY( (checkMoveThrowConstruct<AT,AT>()) );
+    VERIFY( (checkCopyThrowConstruct<AT,IT>()) );
+    VERIFY( (checkMoveThrowConstruct<AT,IT>()) );
+    VERIFY( (checkMoveThrowConstruct<AT,CIT>()) );
+    VERIFY( (checkCopyThrowConstruct<AAT,AAT>()) );
+    VERIFY( (checkMoveThrowConstruct<AAT,AAT>()) );
+    VERIFY( (checkCopyThrowConstruct<AAT,IIT>()) );
+    VERIFY( (checkMoveThrowConstruct<AAT,IIT>()) );
+    VERIFY( (checkCopyThrowConstruct<AAT,IIP>()) );
+    VERIFY( (checkMoveThrowConstruct<AAT,IIP>()) );
+
+    VERIFY( (checkCopyThrowConstruct<AAT,std::tuple<int,A>>()) );
+    VERIFY( (checkMoveThrowConstruct<AAT,std::tuple<int,A>>()) );
+    VERIFY( (checkCopyThrowConstruct<AAT,std::pair<int,A>>()) );
+    VERIFY( (checkMoveThrowConstruct<AAT,std::pair<int,A>>()) );
+
+    VERIFY( (checkCopyThrowConstruct<AAAT,AAAT>()) );
+    VERIFY( (checkMoveThrowConstruct<AAAT,AAAT>()) );
+    VERIFY( (checkCopyThrowConstruct<AAAT,IIAT>()) );
+    VERIFY( (checkMoveThrowConstruct<AAAT,IIAT>()) );
+  }
+}
+namespace NothrowCopyThrowMoveThrowCopyConversionNothrowMoveConversion
+{
+  struct B
+  {
+    B() noexcept(true)
+        {}
+
+    B(const int&) noexcept(false)
+      {  throwing_ctor_called = true; }
+
+    B(int&&) noexcept(true)
+      {}
+
+    B(const B&) noexcept(true)
+      {}
+
+    B(B&&) noexcept(false)
+      {  throwing_ctor_called = true; }
+  };
+
+
+  struct D
+  {
+    D() noexcept(true)
+        {}
+
+    explicit
+    D(const int&) noexcept(false)
+    {  throwing_ctor_called = true; }
+
+    explicit
+    D(int&&) noexcept(true)
+        {}
+
+    explicit
+    D(const D&) noexcept(true)
+      {}
+
+    explicit
+    D(D&&) noexcept(false)
+    {  throwing_ctor_called = true; }
+
+  };
+
+  typedef std::tuple<B> BT;
+  typedef std::tuple<B,B> BBT;
+  typedef std::pair<B,B> BBP;
+  typedef std::tuple<D> DT;
+  typedef std::tuple<D,D> DDT;
+  typedef std::pair<D,D> DDP;
+  typedef std::tuple<int,D> IDT;
+  typedef std::pair<int,D> IDP;
+  typedef std::tuple<int,B> IBT;
+  typedef std::pair<int,B> IBP;
+  typedef std::tuple<D,B> DBT;
+  typedef std::pair<D,B> DBP;
+  typedef std::tuple<B,B,B> BBBT;
+  typedef std::tuple<D,D,D> DDDT;
+  typedef std::tuple<int,D,int> IDIT;
+  typedef std::tuple<int,B,int> IBIT;
+  typedef std::tuple<int,D,B> IDBT;
+
+/* one element tests */
+  static_assert(std::is_nothrow_constructible<BT, int>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, const int>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, int&>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, const int &>::value, "");
+
+  static_assert(std::is_nothrow_constructible<BT, IT>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT,const IT>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, IT&>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, const IT &>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, std::tuple<int&>>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, const std::tuple<int&&>>::value, "");
+
+  static_assert(test_trait::is_nothrow_convertible<int,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const int,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<int&,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const int &,BT>::value,"");
+
+  static_assert(test_trait::is_nothrow_convertible<IT,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IT,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IT&,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IT &,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<std::tuple<int&>,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const std::tuple<int&&>,BT>::value,"");
+
+
+  static_assert(!std::is_nothrow_constructible<BT, B>::value, "");
+  static_assert(std::is_nothrow_constructible<BT,const B>::value, "");
+  static_assert(std::is_nothrow_constructible<BT, B&>::value, "");
+  static_assert(std::is_nothrow_constructible<BT, const B &>::value, "");
+
+  static_assert(!std::is_nothrow_constructible<BT, BT>::value, "");
+  static_assert(std::is_nothrow_constructible<BT,const BT>::value, "");
+  static_assert(std::is_nothrow_constructible<BT, BT&>::value, "");
+  static_assert(std::is_nothrow_constructible<BT, const BT &>::value, "");
+  static_assert(std::is_nothrow_constructible<BT, std::tuple<B&>>::value, "");
+  static_assert(std::is_nothrow_constructible<BT, const std::tuple<B&&>>::value, "");
+
+  static_assert(!test_trait::is_nothrow_convertible<B,BT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const B,BT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<B&,BT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const B &,BT>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<BT,BT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const BT,BT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<BT&,BT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const BT &,BT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<std::tuple<B&>,BT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const std::tuple<B&&>,BT>::value,"");
+
+/* explicit */
+  static_assert(std::is_nothrow_constructible<DT, int>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, const int>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, int&>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, const int &>::value, "");
+
+  static_assert(std::is_nothrow_constructible<DT, IT>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT,const IT>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, IT&>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, const IT &>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, std::tuple<int&>>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, const std::tuple<int&&>>::value, "");
+
+  static_assert(!std::is_nothrow_constructible<DT, D>::value, "");
+  static_assert(std::is_nothrow_constructible<DT,const D>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, D&>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const D &>::value, "");
+
+  static_assert(!std::is_nothrow_constructible<DT, DT>::value, "");
+  static_assert(std::is_nothrow_constructible<DT,const DT>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, DT&>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const DT &>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, std::tuple<D&>>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const std::tuple<D&&>>::value, "");
+
+  static_assert(!test_trait::is_nothrow_convertible<DT,DT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const DT,DT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<DT&,DT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const DT &,DT>::value,"");
+
+/* two elements tests */
+  static_assert(std::is_nothrow_constructible<BBT,IIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,IIT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IIT &>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,IIP>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IIP>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,IIP&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IIP &>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,std::tuple<int&,int&>>::value,"");
+
+  static_assert(test_trait::is_nothrow_convertible<IIT,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIT,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IIT&,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIT &,BBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<IIP,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIP,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IIP&,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIP &,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<std::tuple<int&,int&>,BBT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<BBT,BBT>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,const BBT>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,BBT&>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,const BBT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,BBP>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,const BBP>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,BBP&>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,const BBP &>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,std::tuple<B&,B&>>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<BBT,IBT>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IBT>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,IBT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IBT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,IBP>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IBP>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,IBP&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IBP &>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,std::tuple<const B&,int&&>>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<BBT,BBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const BBT,BBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<BBT&,BBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const BBT &,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<BBP,BBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const BBP,BBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<BBP&,BBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const BBP &,BBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<std::tuple<B&,int&&>,BBT>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<IBT,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IBT,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IBT&,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IBT &,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IBP,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IBP,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IBP&,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IBP &,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<std::tuple<B&,int&>,BBT>::value,"");
+
+
+  static_assert(!std::is_nothrow_constructible<BBT,int&,const int&>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,int&&,const B&>::value,"");
+
+  static_assert(std::is_nothrow_constructible<BBT,B&,const B&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,B&&,const B&&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const B &&,const int&&>::value,"");
+
+/* explicit */
+  static_assert(std::is_nothrow_constructible<DDT,IIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,IIT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IIT &>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,IIP>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IIP>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,IIP&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IIP &>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,std::tuple<int&,int&>>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<DDT,DDT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const DDT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,DDT&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const DDT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,DDP>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const DDP>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,DDP&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const DDP &>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,std::tuple<D&,D&>>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<DDT,IDT>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IDT>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,IDT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IDT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,IDP>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IDP>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,IDP&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IDP &>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,std::tuple<const D&,int&&>>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<DDT,DDT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const DDT,DDT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<DDT&,DDT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const DDT &,DDT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<DDT,int&,const int&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,int&&,const D&>::value,"");
+
+  static_assert(std::is_nothrow_constructible<DDT,D&,const D&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,D&&,const D&&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const D &&,const int&&>::value,"");
+
+/* three elements tests */
+  static_assert(std::is_nothrow_constructible<BBBT,IIIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBBT,const IIIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBBT,IIIT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBBT,const IIIT &>::value,"");
+
+  static_assert(test_trait::is_nothrow_convertible<IIIT,BBBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIIT,BBBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IIIT&,BBBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIIT &,BBBT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<BBBT,BBBT>::value,"");
+  static_assert(std::is_nothrow_constructible<BBBT,const BBBT>::value,"");
+  static_assert(std::is_nothrow_constructible<BBBT,BBBT&>::value,"");
+  static_assert(std::is_nothrow_constructible<BBBT,const BBBT &>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<BBBT,BBBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const BBBT,BBBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<BBBT&,BBBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const BBBT &,BBBT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<BBBT,int&,const int&,int&&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBBT,int&, B&&,const int&&>::value,"");
+  static_assert(std::is_nothrow_constructible<BBBT,int&&, B&,const B&&>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<BBBT,std::tuple<int&,const int&,int&&>>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBBT,std::tuple<int &, B&&,const int&&>>::value,"");
+  static_assert(std::is_nothrow_constructible<BBBT,std::tuple<int &&, B&,const B&&>>::value,"");
+
+/* explicit */
+  static_assert(std::is_nothrow_constructible<DDDT,IIIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDDT,const IIIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDDT,IIIT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDDT,const IIIT &>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<DDDT,DDDT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDDT,const DDDT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDDT,DDDT&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDDT,const DDDT &>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<DDDT,DDDT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const DDDT,DDDT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<DDDT&,DDDT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const DDDT &,DDDT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<DDDT,int&,const int&,int&&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDDT,int &, D&&,const int&&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDDT,int &&, D&,const D&&>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<DDDT,std::tuple<int&,const int&,int&&>>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDDT,std::tuple<int &, D&&,const int&&>>::value,"");
+  static_assert(std::is_nothrow_constructible<DDDT,std::tuple<int &&, D&,const D&&>>::value,"");
+
+
+  void Run()
+  {
+    VERIFY( (checkCopyThrowConstruct<BT, int>()) );
+    VERIFY( (checkMoveThrowConstruct<BT, int>()) );
+    VERIFY( (checkCopyThrowConstruct<BT, B>()) );
+    VERIFY( (checkMoveThrowConstruct<BT, B>()) );
+    VERIFY( (checkCopyThrowConstruct<BT, IT>()) );
+    VERIFY( (checkMoveThrowConstruct<BT, IT>()) );
+    VERIFY( (checkMoveThrowConstruct<BT, CIT>()) );
+    VERIFY( (checkCopyThrowConstruct<BBT, IIT>()) );
+    VERIFY( (checkMoveThrowConstruct<BBT, IIT>()) );
+    VERIFY( (checkCopyThrowConstruct<BBT, IIP>()) );
+    VERIFY( (checkMoveThrowConstruct<BBT, IIP>()) );
+    VERIFY( (checkCopyThrowConstruct<BBT, BBP>()) );
+    VERIFY( (checkMoveThrowConstruct<BBT, BBP>()) );
+    VERIFY( (checkCopyThrowConstruct<BBT, std::tuple<B, int>>()) );
+    VERIFY( (checkMoveThrowConstruct<BBT, std::tuple<B, int>>()) );
+
+    VERIFY( (checkCopyThrowConstruct<DT, int>()) );
+    VERIFY( (checkMoveThrowConstruct<DT, int>()) );
+    VERIFY( (checkCopyThrowConstruct<DT, D>()) );
+    VERIFY( (checkMoveThrowConstruct<DT, D>()) );
+    VERIFY( (checkCopyThrowConstruct<DT, IT>()) );
+    VERIFY( (checkMoveThrowConstruct<DT, IT>()) );
+    VERIFY( (checkMoveThrowConstruct<DT, CIT>()) );
+    VERIFY( (checkCopyThrowConstruct<DDT, IIT>()) );
+    VERIFY( (checkMoveThrowConstruct<DDT, IIT>()) );
+    VERIFY( (checkCopyThrowConstruct<DDT, IIP>()) );
+    VERIFY( (checkMoveThrowConstruct<DDT, IIP>()) );
+    VERIFY( (checkCopyThrowConstruct<DDT, DDP>()) );
+    VERIFY( (checkMoveThrowConstruct<DDT, DDP>()) );
+    VERIFY( (checkCopyThrowConstruct<DDT, std::tuple<D, int>>()) );
+    VERIFY( (checkMoveThrowConstruct<DDT, std::tuple<D, int>>()) );
+
+    VERIFY( (checkCopyThrowConstruct<DBT, IIT>()) );
+    VERIFY( (checkMoveThrowConstruct<DBT, IIT>()) );
+    VERIFY( (checkCopyThrowConstruct<DBT, DBT>()) );
+    VERIFY( (checkMoveThrowConstruct<DBT, DBT>()) );
+    VERIFY( (checkCopyThrowConstruct<DBT, DBP>()) );
+    VERIFY( (checkMoveThrowConstruct<DBT, DBP>()) );
+    VERIFY( (checkCopyThrowConstruct<DBT, IIP>()) );
+    VERIFY( (checkMoveThrowConstruct<DBT, IIP>()) );
+
+
+    VERIFY( (checkCopyThrowConstruct<IDIT, IIIT>()) );
+    VERIFY( (checkMoveThrowConstruct<IDIT, IIIT>()) );
+    VERIFY( (checkCopyThrowConstruct<IDIT, IDIT>()) );
+    VERIFY( (checkMoveThrowConstruct<IDIT, IDIT>()) );
+    VERIFY( (checkCopyThrowConstruct<IBIT, IIIT>()) );
+    VERIFY( (checkMoveThrowConstruct<IBIT, IIIT>()) );
+    VERIFY( (checkCopyThrowConstruct<IBIT, IBIT>()) );
+    VERIFY( (checkMoveThrowConstruct<IBIT, IBIT>()) );
+    VERIFY( (checkCopyThrowConstruct<IDBT, IIIT>()) );
+    VERIFY( (checkMoveThrowConstruct<IDBT, IIIT>()) );
+    VERIFY( (checkCopyThrowConstruct<IDBT, IDBT>()) );
+    VERIFY( (checkMoveThrowConstruct<IDBT, IDBT>()) );
+
+  }
+}
+namespace ThrowCopy
+{
+  struct C
+  {
+    C() noexcept(true)
+       {}
+
+    explicit
+    C(const C&) noexcept(true) {}
+
+  };
+
+  typedef std::tuple<C> CT;
+  typedef std::tuple<C,C> CCT;
+  typedef std::pair<C,C> CCP;
+  typedef std::tuple<int,int,C> IICT;
+
+  static_assert(std::is_nothrow_constructible<CT, C&>::value, "");
+  static_assert(std::is_nothrow_constructible<CT, const C&>::value, "");
+  static_assert(std::is_nothrow_constructible<CT, C&&>::value, "");
+  static_assert(std::is_nothrow_constructible<CT, const C &&>::value, "");
+
+
+  static_assert(std::is_nothrow_constructible<CCT, C&, C&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, const C&, const C&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, C&&, C&&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, const C &&, const C &&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IICT, int, int, C&>::value, "");
+  static_assert(std::is_nothrow_constructible<IICT, int, int, const C&>::value, "");
+  static_assert(std::is_nothrow_constructible<IICT, int, int, C&&>::value, "");
+  static_assert(std::is_nothrow_constructible<IICT, int, int, const C &&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<CT, CT&>::value, "");
+  static_assert(std::is_nothrow_constructible<CT, const CT&>::value, "");
+  static_assert(std::is_nothrow_constructible<CT, CT&&>::value, "");
+  static_assert(std::is_nothrow_constructible<CT, const CT &&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<CCT, CCT&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, const CCT&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, CCT&&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, const CCT &&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<CCT, CCP&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, const CCP&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, CCP&&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, const CCP &&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IICT, IICT&>::value, "");
+  static_assert(std::is_nothrow_constructible<IICT, const IICT&>::value, "");
+  static_assert(std::is_nothrow_constructible<IICT, IICT&&>::value, "");
+  static_assert(std::is_nothrow_constructible<IICT, const IICT &&>::value, "");
+
+}
+namespace ThrowMoveNothrowConversion
+{
+  struct D
+  {
+  D() noexcept(true)
+  {}
+
+  explicit
+  D(const int&) noexcept(true)
+  {}
+
+  explicit
+  D(int&&) noexcept(false)
+  {  throwing_ctor_called = true; }
+
+  };
+
+  typedef std::tuple<D> DT;
+  typedef std::tuple<D,D> DDT;
+  typedef std::pair<D,D> DDP;
+  typedef std::tuple<int,D,int> IDIT;
+
+
+  static_assert(!std::is_nothrow_constructible<DT, int>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const int>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, int&>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const int &>::value, "");
+
+  static_assert(!std::is_nothrow_constructible<DT, IT>::value, "");
+  static_assert(std::is_nothrow_constructible<DT,const IT>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, IT&>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const IT &>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, std::tuple<int&>>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const std::tuple<int&&>>::value, "");
+
+  static_assert(test_trait::is_nothrow_convertible<DT,DT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<D,DT>::value,"");
+
+/* two elements tests */
+  static_assert(!std::is_nothrow_constructible<DDT,IIT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const IIT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,IIT&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const IIT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,IIP>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const IIP>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,IIP&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const IIP &>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,std::tuple<int&,int&>>::value,"");
+
+  static_assert(std::is_nothrow_constructible<DDT,DDT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,DDP>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,std::tuple<int&,D>>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,std::pair<D,int&&>>::value,"");
+
+  static_assert(std::is_convertible<DDT,DDT>::value,"");
+
+/* three elements tests */
+  static_assert(!std::is_nothrow_constructible<IDIT,IIIT>::value,"");
+  static_assert(std::is_nothrow_constructible<IDIT,const IIIT>::value,"");
+  static_assert(std::is_nothrow_constructible<IDIT,IIIT&>::value,"");
+  static_assert(std::is_nothrow_constructible<IDIT,const IIIT &>::value,"");
+
+  static_assert(test_trait::is_nothrow_convertible<IDIT,IDIT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<IDIT,IDIT>::value,"");
+
+  static_assert(std::is_nothrow_constructible<IDIT,int&,const int&,int&&>::value,"");
+  static_assert(std::is_nothrow_constructible<IDIT,int &, D&&,const int&&>::value,"");
+  static_assert(std::is_nothrow_constructible<IDIT,std::tuple<int&,const int&,int&&>>::value,"");
+  static_assert(!std::is_nothrow_constructible<IDIT,std::tuple<int &, int&&,const int&&>>::value,"");
+
+  void Run()
+  {
+    VERIFY( (checkCopyThrowConstruct<DDT, IIT>()) );
+    VERIFY( (checkMoveThrowConstruct<DDT, IIT>()) );
+    VERIFY( (checkCopyThrowConstruct<DDT, std::tuple<D, int>>()) );
+    VERIFY( (checkMoveThrowConstruct<DDT, std::tuple<D, int>>()) );
+  }
+}
+
+int main()
+{
+
+  DefaultConstructionTests::Run();
+
+  ThrowCopyNothrowConversion::Run();
+
+  NothrowCopyThrowMoveThrowCopyConversionNothrowMoveConversion::Run();
+
+  ThrowMoveNothrowConversion::Run();
+
+}
+

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Adding noexcept-specification on tuple constructors (LWG 2899)
  2019-04-23 19:12       ` Nina Dinka Ranns
@ 2019-04-23 21:05         ` Jonathan Wakely
  2019-04-24 10:30           ` Nina Dinka Ranns
  0 siblings, 1 reply; 14+ messages in thread
From: Jonathan Wakely @ 2019-04-23 21:05 UTC (permalink / raw)
  To: Nina Dinka Ranns; +Cc: gcc-patches, libstdc++

On 23/04/19 18:43 +0100, Nina Dinka Ranns wrote:
>On Thu, 18 Apr 2019 at 21:35, Jonathan Wakely <jwakely@redhat.com> wrote:
>>
>> On 16/04/19 17:59 +0100, Nina Dinka Ranns wrote:
>> >On Tue, 16 Apr 2019 at 15:18, Jonathan Wakely <jwakely@redhat.com> wrote:
>> >>
>> >> On 16/04/19 14:08 +0100, Nina Dinka Ranns wrote:
>> >> >Tested on Linux-PPC64
>> >> >Adding noexcept-specification on tuple constructors (LWG 2899)
>> >>
>> >> Thanks, Nina!
>> >>
>> >> This looks great, although as I think Ville has explained we won't
>> >> commit it until the next stage 1, after the GCC 9 release.
>> >ack
>> >
>> >>
>> >> The changes look good, I just have some mostly-stylistic comments,
>> >> which are inline below ...
>> >>
>> >>
>> >> >2019-04-13 Nina Dinka Ranns <dinka.ranns@gmail.com>
>> >> >
>> >> >        Adding noexcept-specification on tuple constructors (LWG 2899)
>> >> >        * libstdc++-v3/include/std/tuple:
>> >> >        (tuple()): Add noexcept-specification.
>> >> >        (tuple(const _Elements&...)): Likewise
>> >> >        (tuple(_UElements&&...)): Likewise
>> >> >        (tuple(const tuple<_UElements...>&)): Likewise
>> >> >        (tuple(tuple<_UElements...>&&)): Likewise
>> >> >        (tuple(const _T1&, const _T2&)): Likewise
>> >> >        (tuple(_U1&&, _U2&&)): Likewise
>> >> >        (tuple(const tuple<_U1, _U2>&): Likewise
>> >> >        (tuple(tuple<_U1, _U2>&&): Likewise
>> >> >        (tuple(const pair<_U1, _U2>&): Likewise
>> >> >        (tuple(pair<_U1, _U2>&&): Likewise
>> >> >
>> >> >
>> >>
>> >> There should be no blank lines in the changelog entry here. A single
>> >> change should be recorded as a single block in the changelog, with no
>> >> blank lines within it.
>> >ack. Do you need me to do anything about this or is it for future
>> >reference only ?
>>
>> For future reference. Whoever commits the patch can correct the
>> changelog.
>>
>> >>
>> >> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc: New
>> >> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs2.cc: New
>> >> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs3.cc: New
>> >> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs4.cc: New
>> >> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs5.cc: New
>> >> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs6.cc: New
>> >>
>> >> This is a lot of new test files for a small-ish QoI feature. Could
>> >> they be combined into one file?  Generally we do want one test file
>> >> per feature, but I think all of these are arguably testing one feature
>> >> (just on different constructors). The downside of lots of smaller
>> >> files is that we have to compile+assemble+link+run each one, which
>> >> adds several fork()s to launch a new process for each step. On some
>> >> platforms that can be quite slow.
>> >I can do that, but there may be an issue. See below.
>> >
>> >>
>> >>
>> >> >@@ -624,6 +634,7 @@
>> >> >                   && (sizeof...(_Elements) >= 1),
>> >> >         bool>::type=true>
>> >> >         constexpr tuple(_UElements&&... __elements)
>> >> >+        noexcept(__and_<is_nothrow_constructible<_Elements,_UElements&&>...>::value)
>> >>
>> >> Can this be __nothrow_constructible<_UElements>() ?
>> >It should have been that in the first place. Apologies. Fixed.
>> >
>> >
>> >>
>> >> >         : _Inherited(std::forward<_UElements>(__elements)...) { }
>> >> >
>> >> >       template<typename... _UElements, typename
>> >> >@@ -635,6 +646,7 @@
>> >> >                   && (sizeof...(_Elements) >= 1),
>> >> >         bool>::type=false>
>> >> >         explicit constexpr tuple(_UElements&&... __elements)
>> >> >+        noexcept(__nothrow_constructible<_UElements&&...>())
>> >>
>> >> The && here is redundant, though harmless.
>> >>
>> >> is_constructible<T,U&&> is exactly equivalent to is_constructible<T,U>
>> >> because U means construction from an rvalue of type U and so does U&&.
>> >>
>> >> It's fine to leave the && there though.
>> >I'm happy to go either way. The only reason I used && form is because
>> >it mimics the wording in the LWG resolution.
>>
>> I suspect if STL had reviewed the wording in the resolution he'd have
>> asked for the && to be removed :-)
>:) ack. Removed.
>
>
>>
>>
>> >> >@@ -966,6 +995,7 @@
>> >> >                 && !is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value,
>> >> >       bool>::type = true>
>> >> >         constexpr tuple(_U1&& __a1, _U2&& __a2)
>> >> >+        noexcept(__nothrow_constructible<_U1&&,_U2&&>())
>> >>
>> >> There should be a space after the comma here, and all the later
>> >> additions in the file.
>> >ack. Fixed
>> >
>> >>
>> >>
>> >> >Index: libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc
>> >> >===================================================================
>> >> >--- libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc        (nonexistent)
>> >> >+++ libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc        (working copy)
>> >> >@@ -0,0 +1,191 @@
>> >> >+// { dg-options { -std=gnu++2a } }
>> >> >+// { dg-do run { target c++2a } }
>> >>
>> >> This new file doesn't use std::is_nothrow_convertible so could just
>> >> use: { dg-do run { target c++11 } } and no dg-options.
>> >>
>> >> For the other new tests that do use is_nothrow_convertible, I'm
>> >> already planning to add std::is_nothrow_convertible for our internal
>> >> use in C++11, so they could use that.
>> >>
>> >> Alternatively, the test files themselves could define:
>> >>
>> >> template<typename From, typename To>
>> >>   struct is_nothrow_convertible
>> >>   : std::integral_constant<bool,
>> >>       is_convertible<From, To> && is_nothrow_constructible<Fo, From>>
>> >>   { };
>> >>
>> >> and then use that. That way we can test the exception specs are
>> >> correct in C++11 mode, the default C++14 mode, and C++17 mode.
>> >> Otherwise we're adding code that affects all those modes but only
>> >> testing it works correctly for the experimental C++2a mode.
>> >
>> >There is a reason why the tests are only C++2a mode. The semantics of
>> >copy construction changed between C++14 and C++17, the effect of which
>> >is that the is_nothrow_convertible (or its equivalent work around) in
>> >certain cases doesn't evaluate the same before and after C++17. After
>> >discussing this with Ville, we decided to only test C++2a because
>> >that's the target of the library issue and because C++2a provided
>>
>> But this isn't actually related to the library issue. The proposed
>> resolution that you're implementing doesn't fix the issue! The
>> discussion in the issue says "The description doesn't match the
>> resolution" and that's correct. That's why I've provided a new
>> resolution to the issue. What you're doing is a Good Thing anyway,
>> even if it doesn't solve LWG 2899. But since it isn't a fix for 2899,
>> which version of C++ the issue targets is irrelevant. You're applying
>> a change that affects std::tuple unconditionally, from C++11 onwards.
>> You're changing the code for C++11, so it should be tested for C++11.
>>
>> It would be appropriate to only test C++2a if you were adding
>> exception specifications that only applied for C++2a, like so:
>>
>>         constexpr tuple(_UElements&&... __elements)
>> #if __cplusplus > 201703L
>>         noexcept(__and_<is_nothrow_constructible<_Elements,_UElements&&>...>::value)
>> #endif
>>
>> But that's not what your patch does (and not what we want it to do).
>>
>> So I really think we need *some* tests that can run in C++11 mode.
>> They wouldn't have to be as extensive and thorough as the ones you've
>> provided, but if we make changes that affect C++11/14/17 then we
>> should test those changes.
>Ok, I now have a set of tests for c++11/14 and a set for C++17/20.
>
>>
>> >std::is_nothrow_convertible so I could do away with my copy conversion
>> >helper functions.
>> >Extending the tests to earlier standards would mean having two sets of
>> >test expectations (one for pre C++17 copy conversion semantics, and
>> >one for C++17 onwards). Would you like me to do that ?
>>
>> Can you show an example of the different semantics? What behaves
>> differently in C++14?
>>
>> If the library provided a std::__is_nothrow_convertible trait for
>> C++11 (with the same implementation as C++20's
>> std::is_nothrow_convertible) and your tests used that, which test
>> expectations would be affected?
>
>Copy initialization pre C++17 involved creating a temporary of
>destination type and then copying/moving the temporary to the result.
>This means that a hypothetical std::__is_nothrow_convertible
>implementation pre C++17 involves an additional call to a copy/move
>constructor and that in some cases changes the nothrow outcome.
>
>Here is an example of such a case :
>https://wandbox.org/permlink/PppTzLXrZH2Dk4eo
>
>It will give different result for C++11/14 and C++17/20

Thanks for the demo. Arguably it's a misfeature of the
is_nothrow_convertible trait, and it should give the same result in
C++14 and C++17 (but as it only exists in C++2a that's not a very good
argument to make ;-). This topic came up on the LWG reflector recently
and https://wg21.link/lwg3194 was opened (the issue doesn't capture
the resulting discussion).

To make the trait's behaviour consistent we could use a
braced-init-list:

  template<typename _From1, typename _To1>
    static bool_constant<noexcept(__test_aux<_To1>({std::declval<_From1>()}))>
    __test(int);

Both before and after C++17 this tests only whether the conversion
throws, and not whether the (possibly elided) copy/move construction
can throw. Defining your test_trait that way might be preferable,
because it means you can test *just* the converting constructor's
exception specification in isolation, rather than the combination of
two exception specifications on two constructors.

The result of is_nothrow_convertible is meaningful for user code
performing such conversions (i.e. if they're performing the conversion
in C++14 then they care about the move ctor, but in C++17 they don't).
But the purpose of our tests is to verify that the exception specs
you've added do the right thing. And for that, it's probably better to
have a trait that tests one thing at a time.

Unless I'm mistaken, if your tests used that trait instead of
is_nothrow_convertible as defined in C++2a, you wouldn't need separate
tests for C++11/14 and C++17/2a, right? You could just take the
noexcept_specs_cpp17.cc test and use it for all dialects.


>The new diff containing changes addressing review comments is attached
>to this e-mail.

Thanks. All the changes in <tuple> look good, except for some
whitespace errors that git noticed:

/dev/shm/noexcept_tuple_v2.diff:79: trailing whitespace.
        explicit constexpr tuple(const tuple<_UElements...>& __in)        
/dev/shm/noexcept_tuple_v2.diff:108: space before tab in indent.
                is_nothrow_constructible<_T2, _U2>>::value;
/dev/shm/noexcept_tuple_v2.diff:119: space before tab in indent.
                        is_nothrow_default_constructible<_T2>>::value)
/dev/shm/noexcept_tuple_v2.diff:128: space before tab in indent.
                        is_nothrow_default_constructible<_T2>>::value)

In the new test files you define is_nothrow_constructible_v but then
never use it. It could be removed (or could be used).

The test_trait helper types doesn't need to use reserved names, i.e.
they could use From and To and test, instead of _From and _To and
__test. 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Adding noexcept-specification on tuple constructors (LWG 2899)
  2019-04-23 21:05         ` Jonathan Wakely
@ 2019-04-24 10:30           ` Nina Dinka Ranns
  2019-04-24 12:47             ` Jonathan Wakely
  0 siblings, 1 reply; 14+ messages in thread
From: Nina Dinka Ranns @ 2019-04-24 10:30 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: gcc-patches, libstdc++

[-- Attachment #1: Type: text/plain, Size: 12589 bytes --]

On Tue, 23 Apr 2019 at 21:28, Jonathan Wakely <jwakely@redhat.com> wrote:
>
> On 23/04/19 18:43 +0100, Nina Dinka Ranns wrote:
> >On Thu, 18 Apr 2019 at 21:35, Jonathan Wakely <jwakely@redhat.com> wrote:
> >>
> >> On 16/04/19 17:59 +0100, Nina Dinka Ranns wrote:
> >> >On Tue, 16 Apr 2019 at 15:18, Jonathan Wakely <jwakely@redhat.com> wrote:
> >> >>
> >> >> On 16/04/19 14:08 +0100, Nina Dinka Ranns wrote:
> >> >> >Tested on Linux-PPC64
> >> >> >Adding noexcept-specification on tuple constructors (LWG 2899)
> >> >>
> >> >> Thanks, Nina!
> >> >>
> >> >> This looks great, although as I think Ville has explained we won't
> >> >> commit it until the next stage 1, after the GCC 9 release.
> >> >ack
> >> >
> >> >>
> >> >> The changes look good, I just have some mostly-stylistic comments,
> >> >> which are inline below ...
> >> >>
> >> >>
> >> >> >2019-04-13 Nina Dinka Ranns <dinka.ranns@gmail.com>
> >> >> >
> >> >> >        Adding noexcept-specification on tuple constructors (LWG 2899)
> >> >> >        * libstdc++-v3/include/std/tuple:
> >> >> >        (tuple()): Add noexcept-specification.
> >> >> >        (tuple(const _Elements&...)): Likewise
> >> >> >        (tuple(_UElements&&...)): Likewise
> >> >> >        (tuple(const tuple<_UElements...>&)): Likewise
> >> >> >        (tuple(tuple<_UElements...>&&)): Likewise
> >> >> >        (tuple(const _T1&, const _T2&)): Likewise
> >> >> >        (tuple(_U1&&, _U2&&)): Likewise
> >> >> >        (tuple(const tuple<_U1, _U2>&): Likewise
> >> >> >        (tuple(tuple<_U1, _U2>&&): Likewise
> >> >> >        (tuple(const pair<_U1, _U2>&): Likewise
> >> >> >        (tuple(pair<_U1, _U2>&&): Likewise
> >> >> >
> >> >> >
> >> >>
> >> >> There should be no blank lines in the changelog entry here. A single
> >> >> change should be recorded as a single block in the changelog, with no
> >> >> blank lines within it.
> >> >ack. Do you need me to do anything about this or is it for future
> >> >reference only ?
> >>
> >> For future reference. Whoever commits the patch can correct the
> >> changelog.
> >>
> >> >>
> >> >> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc: New
> >> >> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs2.cc: New
> >> >> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs3.cc: New
> >> >> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs4.cc: New
> >> >> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs5.cc: New
> >> >> >        * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs6.cc: New
> >> >>
> >> >> This is a lot of new test files for a small-ish QoI feature. Could
> >> >> they be combined into one file?  Generally we do want one test file
> >> >> per feature, but I think all of these are arguably testing one feature
> >> >> (just on different constructors). The downside of lots of smaller
> >> >> files is that we have to compile+assemble+link+run each one, which
> >> >> adds several fork()s to launch a new process for each step. On some
> >> >> platforms that can be quite slow.
> >> >I can do that, but there may be an issue. See below.
> >> >
> >> >>
> >> >>
> >> >> >@@ -624,6 +634,7 @@
> >> >> >                   && (sizeof...(_Elements) >= 1),
> >> >> >         bool>::type=true>
> >> >> >         constexpr tuple(_UElements&&... __elements)
> >> >> >+        noexcept(__and_<is_nothrow_constructible<_Elements,_UElements&&>...>::value)
> >> >>
> >> >> Can this be __nothrow_constructible<_UElements>() ?
> >> >It should have been that in the first place. Apologies. Fixed.
> >> >
> >> >
> >> >>
> >> >> >         : _Inherited(std::forward<_UElements>(__elements)...) { }
> >> >> >
> >> >> >       template<typename... _UElements, typename
> >> >> >@@ -635,6 +646,7 @@
> >> >> >                   && (sizeof...(_Elements) >= 1),
> >> >> >         bool>::type=false>
> >> >> >         explicit constexpr tuple(_UElements&&... __elements)
> >> >> >+        noexcept(__nothrow_constructible<_UElements&&...>())
> >> >>
> >> >> The && here is redundant, though harmless.
> >> >>
> >> >> is_constructible<T,U&&> is exactly equivalent to is_constructible<T,U>
> >> >> because U means construction from an rvalue of type U and so does U&&.
> >> >>
> >> >> It's fine to leave the && there though.
> >> >I'm happy to go either way. The only reason I used && form is because
> >> >it mimics the wording in the LWG resolution.
> >>
> >> I suspect if STL had reviewed the wording in the resolution he'd have
> >> asked for the && to be removed :-)
> >:) ack. Removed.
> >
> >
> >>
> >>
> >> >> >@@ -966,6 +995,7 @@
> >> >> >                 && !is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value,
> >> >> >       bool>::type = true>
> >> >> >         constexpr tuple(_U1&& __a1, _U2&& __a2)
> >> >> >+        noexcept(__nothrow_constructible<_U1&&,_U2&&>())
> >> >>
> >> >> There should be a space after the comma here, and all the later
> >> >> additions in the file.
> >> >ack. Fixed
> >> >
> >> >>
> >> >>
> >> >> >Index: libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc
> >> >> >===================================================================
> >> >> >--- libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc        (nonexistent)
> >> >> >+++ libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc        (working copy)
> >> >> >@@ -0,0 +1,191 @@
> >> >> >+// { dg-options { -std=gnu++2a } }
> >> >> >+// { dg-do run { target c++2a } }
> >> >>
> >> >> This new file doesn't use std::is_nothrow_convertible so could just
> >> >> use: { dg-do run { target c++11 } } and no dg-options.
> >> >>
> >> >> For the other new tests that do use is_nothrow_convertible, I'm
> >> >> already planning to add std::is_nothrow_convertible for our internal
> >> >> use in C++11, so they could use that.
> >> >>
> >> >> Alternatively, the test files themselves could define:
> >> >>
> >> >> template<typename From, typename To>
> >> >>   struct is_nothrow_convertible
> >> >>   : std::integral_constant<bool,
> >> >>       is_convertible<From, To> && is_nothrow_constructible<Fo, From>>
> >> >>   { };
> >> >>
> >> >> and then use that. That way we can test the exception specs are
> >> >> correct in C++11 mode, the default C++14 mode, and C++17 mode.
> >> >> Otherwise we're adding code that affects all those modes but only
> >> >> testing it works correctly for the experimental C++2a mode.
> >> >
> >> >There is a reason why the tests are only C++2a mode. The semantics of
> >> >copy construction changed between C++14 and C++17, the effect of which
> >> >is that the is_nothrow_convertible (or its equivalent work around) in
> >> >certain cases doesn't evaluate the same before and after C++17. After
> >> >discussing this with Ville, we decided to only test C++2a because
> >> >that's the target of the library issue and because C++2a provided
> >>
> >> But this isn't actually related to the library issue. The proposed
> >> resolution that you're implementing doesn't fix the issue! The
> >> discussion in the issue says "The description doesn't match the
> >> resolution" and that's correct. That's why I've provided a new
> >> resolution to the issue. What you're doing is a Good Thing anyway,
> >> even if it doesn't solve LWG 2899. But since it isn't a fix for 2899,
> >> which version of C++ the issue targets is irrelevant. You're applying
> >> a change that affects std::tuple unconditionally, from C++11 onwards.
> >> You're changing the code for C++11, so it should be tested for C++11.
> >>
> >> It would be appropriate to only test C++2a if you were adding
> >> exception specifications that only applied for C++2a, like so:
> >>
> >>         constexpr tuple(_UElements&&... __elements)
> >> #if __cplusplus > 201703L
> >>         noexcept(__and_<is_nothrow_constructible<_Elements,_UElements&&>...>::value)
> >> #endif
> >>
> >> But that's not what your patch does (and not what we want it to do).
> >>
> >> So I really think we need *some* tests that can run in C++11 mode.
> >> They wouldn't have to be as extensive and thorough as the ones you've
> >> provided, but if we make changes that affect C++11/14/17 then we
> >> should test those changes.
> >Ok, I now have a set of tests for c++11/14 and a set for C++17/20.
> >
> >>
> >> >std::is_nothrow_convertible so I could do away with my copy conversion
> >> >helper functions.
> >> >Extending the tests to earlier standards would mean having two sets of
> >> >test expectations (one for pre C++17 copy conversion semantics, and
> >> >one for C++17 onwards). Would you like me to do that ?
> >>
> >> Can you show an example of the different semantics? What behaves
> >> differently in C++14?
> >>
> >> If the library provided a std::__is_nothrow_convertible trait for
> >> C++11 (with the same implementation as C++20's
> >> std::is_nothrow_convertible) and your tests used that, which test
> >> expectations would be affected?
> >
> >Copy initialization pre C++17 involved creating a temporary of
> >destination type and then copying/moving the temporary to the result.
> >This means that a hypothetical std::__is_nothrow_convertible
> >implementation pre C++17 involves an additional call to a copy/move
> >constructor and that in some cases changes the nothrow outcome.
> >
> >Here is an example of such a case :
> >https://wandbox.org/permlink/PppTzLXrZH2Dk4eo
> >
> >It will give different result for C++11/14 and C++17/20
>
> Thanks for the demo. Arguably it's a misfeature of the
> is_nothrow_convertible trait, and it should give the same result in
> C++14 and C++17 (but as it only exists in C++2a that's not a very good
> argument to make ;-). This topic came up on the LWG reflector recently
> and https://wg21.link/lwg3194 was opened (the issue doesn't capture
> the resulting discussion).
I'd argue the trait is fine as it is. The semantics of conversion are
different in C++14 and C++17, and there is a theoretical possibility
that a conversion may involve a temporary in C++11/14. Like you say,
it's c++2a only, so it's a pointless discussion. :)

>
> To make the trait's behaviour consistent we could use a
> braced-init-list:
>
>   template<typename _From1, typename _To1>
>     static bool_constant<noexcept(__test_aux<_To1>({std::declval<_From1>()}))>
>     __test(int);

clever :) Using list initialization skips the temporary. I like it. :)

>
> Both before and after C++17 this tests only whether the conversion
> throws, and not whether the (possibly elided) copy/move construction
> can throw. Defining your test_trait that way might be preferable,
> because it means you can test *just* the converting constructor's
> exception specification in isolation, rather than the combination of
> two exception specifications on two constructors.
>
> The result of is_nothrow_convertible is meaningful for user code
> performing such conversions (i.e. if they're performing the conversion
> in C++14 then they care about the move ctor, but in C++17 they don't).
> But the purpose of our tests is to verify that the exception specs
> you've added do the right thing. And for that, it's probably better to
> have a trait that tests one thing at a time.
>
> Unless I'm mistaken, if your tests used that trait instead of
> is_nothrow_convertible as defined in C++2a, you wouldn't need separate
> tests for C++11/14 and C++17/2a, right? You could just take the
> noexcept_specs_cpp17.cc test and use it for all dialects.

Done.

>
>
> >The new diff containing changes addressing review comments is attached
> >to this e-mail.
>
> Thanks. All the changes in <tuple> look good, except for some
> whitespace errors that git noticed:
>
> /dev/shm/noexcept_tuple_v2.diff:79: trailing whitespace.
>         explicit constexpr tuple(const tuple<_UElements...>& __in)
> /dev/shm/noexcept_tuple_v2.diff:108: space before tab in indent.
>                 is_nothrow_constructible<_T2, _U2>>::value;
> /dev/shm/noexcept_tuple_v2.diff:119: space before tab in indent.
>                         is_nothrow_default_constructible<_T2>>::value)
> /dev/shm/noexcept_tuple_v2.diff:128: space before tab in indent.
>                         is_nothrow_default_constructible<_T2>>::value)
Fixed (I think, it's a fiddly check in my environment so I may have
missed something)

>
> In the new test files you define is_nothrow_constructible_v but then
> never use it. It could be removed (or could be used).
Removed

>
> The test_trait helper types doesn't need to use reserved names, i.e.
> they could use From and To and test, instead of _From and _To and
> __test.
Renamed.

New diff attached.
Best,
Nina

[-- Attachment #2: noexcept_tuple_v3.diff --]
[-- Type: application/octet-stream, Size: 55228 bytes --]

Index: libstdc++-v3/include/std/tuple
===================================================================
--- libstdc++-v3/include/std/tuple	(revision 268955)
+++ libstdc++-v3/include/std/tuple	(working copy)
@@ -552,6 +552,12 @@
 	  return
 	    __and_<is_nothrow_assignable<_Elements&, _UElements>...>::value;
 	}
+      template<typename... _UElements>
+	static constexpr bool __nothrow_constructible()
+	{
+	  return
+	    __and_<is_nothrow_constructible<_Elements, _UElements>...>::value;
+	}
 
     public:
       template<typename _Dummy = void,
@@ -559,6 +565,7 @@
                                     _ImplicitlyDefaultConstructibleTuple(),
                                   bool>::type = true>
       constexpr tuple()
+      noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
       : _Inherited() { }
 
       template<typename _Dummy = void,
@@ -569,6 +576,7 @@
                                     _ImplicitlyDefaultConstructibleTuple(),
                                   bool>::type = false>
       explicit constexpr tuple()
+      noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
       : _Inherited() { }
 
       // Shortcut for the cases where constructors taking _Elements...
@@ -586,6 +594,7 @@
                  && (sizeof...(_Elements) >= 1),
                bool>::type=true>
         constexpr tuple(const _Elements&... __elements)
+        noexcept(__nothrow_constructible<const _Elements&...>())
       : _Inherited(__elements...) { }
 
       template<typename _Dummy = void,
@@ -597,6 +606,7 @@
                  && (sizeof...(_Elements) >= 1),
                bool>::type=false>
       explicit constexpr tuple(const _Elements&... __elements)
+      noexcept(__nothrow_constructible<const _Elements&...>())
       : _Inherited(__elements...) { }
 
       // Shortcut for the cases where constructors taking _UElements...
@@ -624,6 +634,7 @@
                   && (sizeof...(_Elements) >= 1),
         bool>::type=true>
         constexpr tuple(_UElements&&... __elements)
+        noexcept(__nothrow_constructible<_UElements...>())
         : _Inherited(std::forward<_UElements>(__elements)...) { }
 
       template<typename... _UElements, typename
@@ -635,6 +646,7 @@
                   && (sizeof...(_Elements) >= 1),
         bool>::type=false>
         explicit constexpr tuple(_UElements&&... __elements)
+        noexcept(__nothrow_constructible<_UElements...>())
 	: _Inherited(std::forward<_UElements>(__elements)...) {	}
 
       constexpr tuple(const tuple&) = default;
@@ -656,6 +668,7 @@
                     _NonNestedTuple<const tuple<_UElements...>&>(),
         bool>::type=true>
         constexpr tuple(const tuple<_UElements...>& __in)
+        noexcept(__nothrow_constructible<const _UElements&...>())
         : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
         { }
 
@@ -668,6 +681,7 @@
                     _NonNestedTuple<const tuple<_UElements...>&>(),
         bool>::type=false>
         explicit constexpr tuple(const tuple<_UElements...>& __in)
+        noexcept(__nothrow_constructible<const _UElements&...>())
         : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
         { }
 
@@ -680,6 +694,7 @@
                     _NonNestedTuple<tuple<_UElements...>&&>(),
         bool>::type=true>
         constexpr tuple(tuple<_UElements...>&& __in)
+        noexcept(__nothrow_constructible<_UElements...>())
         : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
 
       template<typename... _UElements, typename _Dummy = void, typename
@@ -691,6 +706,7 @@
                     _NonNestedTuple<tuple<_UElements...>&&>(),
         bool>::type=false>
         explicit constexpr tuple(tuple<_UElements...>&& __in)
+        noexcept(__nothrow_constructible<_UElements...>())
         : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
 
       // Allocator-extended constructors.
@@ -908,6 +924,13 @@
 			is_nothrow_assignable<_T2&, _U2>>::value;
 	}
 
+      template<typename _U1, typename _U2>
+    static constexpr bool __nothrow_constructible()
+    {
+      return __and_<is_nothrow_constructible<_T1, _U1>,
+			is_nothrow_constructible<_T2, _U2>>::value;
+    }
+
     public:
       template <typename _U1 = _T1,
                 typename _U2 = _T2,
@@ -916,6 +939,8 @@
                                      __is_implicitly_default_constructible<_U2>>
                                    ::value, bool>::type = true>
 	constexpr tuple()
+	noexcept(__and_<is_nothrow_default_constructible<_T1>,
+			is_nothrow_default_constructible<_T2>>::value)
 	: _Inherited() { }
 
       template <typename _U1 = _T1,
@@ -929,6 +954,8 @@
                              __is_implicitly_default_constructible<_U2>>>>
                   ::value, bool>::type = false>
 	explicit constexpr tuple()
+	noexcept(__and_<is_nothrow_default_constructible<_T1>,
+			is_nothrow_default_constructible<_T2>>::value)
 	: _Inherited() { }
 
       // Shortcut for the cases where constructors taking _T1, _T2
@@ -943,6 +970,7 @@
                            _ImplicitlyConvertibleTuple<_T1, _T2>(),
 	bool>::type = true>
         constexpr tuple(const _T1& __a1, const _T2& __a2)
+        noexcept(__nothrow_constructible<const _T1&, const _T2&>())
         : _Inherited(__a1, __a2) { }
 
       template<typename _Dummy = void, typename
@@ -952,6 +980,7 @@
                            _ImplicitlyConvertibleTuple<_T1, _T2>(),
 	bool>::type = false>
         explicit constexpr tuple(const _T1& __a1, const _T2& __a2)
+        noexcept(__nothrow_constructible<const _T1&, const _T2&>())
         : _Inherited(__a1, __a2) { }
 
       // Shortcut for the cases where constructors taking _U1, _U2
@@ -966,6 +995,7 @@
 	          && !is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value,
 	bool>::type = true>
         constexpr tuple(_U1&& __a1, _U2&& __a2)
+        noexcept(__nothrow_constructible<_U1, _U2>())
 	: _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
 
       template<typename _U1, typename _U2, typename
@@ -976,6 +1006,7 @@
 	          && !is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value,
 	bool>::type = false>
         explicit constexpr tuple(_U1&& __a1, _U2&& __a2)
+        noexcept(__nothrow_constructible<_U1, _U2>())
 	: _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
 
       constexpr tuple(const tuple&) = default;
@@ -989,6 +1020,7 @@
                     _ImplicitlyConvertibleTuple<_U1, _U2>(),
 	bool>::type = true>
         constexpr tuple(const tuple<_U1, _U2>& __in)
+        noexcept(__nothrow_constructible<const _U1&, const _U2&>())
 	: _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
 
       template<typename _U1, typename _U2, typename
@@ -998,6 +1030,7 @@
                     _ImplicitlyConvertibleTuple<_U1, _U2>(),
 	bool>::type = false>
         explicit constexpr tuple(const tuple<_U1, _U2>& __in)
+        noexcept(__nothrow_constructible<const _U1&, const _U2&>())
 	: _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
 
       template<typename _U1, typename _U2, typename
@@ -1007,6 +1040,7 @@
                     _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
 	bool>::type = true>
         constexpr tuple(tuple<_U1, _U2>&& __in)
+        noexcept(__nothrow_constructible<_U1, _U2>())
 	: _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
 
       template<typename _U1, typename _U2, typename
@@ -1016,6 +1050,7 @@
                     _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
 	bool>::type = false>
         explicit constexpr tuple(tuple<_U1, _U2>&& __in)
+        noexcept(__nothrow_constructible<_U1, _U2>())
 	: _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
 
       template<typename _U1, typename _U2, typename
@@ -1025,6 +1060,7 @@
                     _ImplicitlyConvertibleTuple<_U1, _U2>(),
 	bool>::type = true>
         constexpr tuple(const pair<_U1, _U2>& __in)
+        noexcept(__nothrow_constructible<const _U1&, const _U2&>())
 	: _Inherited(__in.first, __in.second) { }
 
       template<typename _U1, typename _U2, typename
@@ -1034,6 +1070,7 @@
                     _ImplicitlyConvertibleTuple<_U1, _U2>(),
 	bool>::type = false>
         explicit constexpr tuple(const pair<_U1, _U2>& __in)
+        noexcept(__nothrow_constructible<const _U1&, const _U2&>())
 	: _Inherited(__in.first, __in.second) { }
 
       template<typename _U1, typename _U2, typename
@@ -1043,6 +1080,7 @@
                     _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
 	bool>::type = true>
         constexpr tuple(pair<_U1, _U2>&& __in)
+        noexcept(__nothrow_constructible<_U1, _U2>())
 	: _Inherited(std::forward<_U1>(__in.first),
 		     std::forward<_U2>(__in.second)) { }
 
@@ -1053,6 +1091,7 @@
                     _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
 	bool>::type = false>
         explicit constexpr tuple(pair<_U1, _U2>&& __in)
+        noexcept(__nothrow_constructible<_U1, _U2>())
 	: _Inherited(std::forward<_U1>(__in.first),
 		     std::forward<_U2>(__in.second)) { }
 
Index: libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc
===================================================================
--- libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc	(nonexistent)
+++ libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc	(working copy)
@@ -0,0 +1,943 @@
+//{ dg-do run { target c++11 } }
+
+// 2019-04-10  Nina Dinka Ranns  <dinka.ranns@gmail.com>
+//
+// Copyright (C) 2019 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>
+#include <testsuite_tr1.h>
+#include <utility>
+
+using namespace __gnu_test;
+
+bool throwing_ctor_called = false;
+
+namespace test_trait{
+   template <bool B>
+   using bool_constant = std::integral_constant<bool, B>;
+
+   template<typename From, typename To,
+           bool = std::__or_<std::is_void<From>, std::is_function<To>,
+		   std::is_array<To>>::value>
+    struct is_nt_convertible_helper
+    : std::is_void<To>
+    { };
+
+  template<typename From, typename To>
+    class is_nt_convertible_helper<From, To, false>
+    {
+      template<typename To1>
+	static void test_aux(To1) noexcept;
+
+      template<typename From1, typename To1>
+	static bool_constant<noexcept(test_aux<To1>({std::declval<From1>()}))>
+	test(int);
+
+      template<typename, typename>
+	static std::false_type
+	test(...);
+
+    public:
+      using type = decltype(test<From, To>(0));
+    };
+
+  /// is_nothrow_convertible
+  template<typename From, typename To>
+    struct is_nothrow_convertible
+    : public is_nt_convertible_helper<From, To>::type
+    { };
+}
+
+template<typename T>
+bool  checkDefaultThrowConstruct()
+{
+  throwing_ctor_called = false;
+  bool deduced_nothrow = std::is_nothrow_constructible<T>::value;
+  T t{};
+  return throwing_ctor_called != deduced_nothrow;
+}
+template<typename T, typename U>
+bool  checkCopyThrowConstruct()
+{
+  throwing_ctor_called = false;
+  bool deduced_nothrow = std::is_nothrow_constructible<T, U&>::value;
+  U u;
+  T t{u};
+  return throwing_ctor_called != deduced_nothrow;
+}
+template<typename T, typename U>
+bool  checkMoveThrowConstruct()
+{
+  throwing_ctor_called = false;
+  bool deduced_nothrow = std::is_nothrow_constructible<T, U&&>::value;
+  U u;
+  T t{std::move(u)};
+  return throwing_ctor_called != deduced_nothrow;
+}
+
+typedef std::tuple<int> IT;
+typedef std::tuple<const int> CIT;
+typedef std::tuple<int&&> RVIT;
+typedef std::tuple<int, int> IIT;
+typedef std::pair<int, int> IIP;
+typedef std::tuple<int, int, int> IIIT;
+
+namespace DefaultConstructionTests
+{
+  struct NoexceptDC
+  {
+    NoexceptDC() noexcept(true){}
+  };
+
+  struct ExceptDC
+  {
+    ExceptDC() noexcept(false)
+      {  throwing_ctor_called = true; }
+  };
+
+  struct ExplicitNoexceptDC
+  {
+    explicit ExplicitNoexceptDC() noexcept(true)
+        {}
+  };
+
+  struct ExplicitExceptDC
+  {
+    explicit ExplicitExceptDC() noexcept(false)
+        {  throwing_ctor_called = true; }
+  };
+
+  typedef std::tuple<NoexceptDC> NDT;
+  typedef std::tuple<ExceptDC> EDT;
+  typedef std::tuple<ExplicitNoexceptDC> X_NDT;
+  typedef std::tuple<ExplicitExceptDC> X_EDT;
+
+  typedef std::tuple<NoexceptDC,NoexceptDC> NNDT;
+  typedef std::tuple<ExceptDC,ExceptDC> EEDT;
+  typedef std::tuple<ExceptDC,NoexceptDC> ENDT;
+  typedef std::tuple<ExplicitNoexceptDC,NoexceptDC> X_NNDT;
+  typedef std::tuple<ExplicitExceptDC,ExceptDC> X_EEDT;
+  typedef std::tuple<ExceptDC,ExplicitNoexceptDC> X_ENDT;
+
+  typedef std::tuple<long, NoexceptDC, NoexceptDC> LNDNDT;
+  typedef std::tuple<long, NoexceptDC, ExceptDC> LNDEDT;
+  typedef std::tuple<long, ExplicitNoexceptDC, NoexceptDC> X_LNEDNDT;
+  typedef std::tuple<long, ExplicitNoexceptDC, ExceptDC> X_LNEDEDT;
+  typedef std::tuple<long, ExplicitExceptDC, ExceptDC> X_LEEDEDT;
+
+
+  /* if it has E in the name, it contains a type that throws when default constructed */
+  static_assert(std::is_nothrow_constructible<IT>::value, "");
+  static_assert(std::is_nothrow_constructible<NDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<EDT>::value, "");
+  static_assert(std::is_nothrow_constructible<X_NDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<X_EDT>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IIT>::value, "");
+  static_assert(std::is_nothrow_constructible<NNDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<EEDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<ENDT>::value, "");
+  static_assert(std::is_nothrow_constructible<X_NNDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<X_EEDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<X_ENDT>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IIIT>::value, "");
+  static_assert(std::is_nothrow_constructible<LNDNDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<LNDEDT>::value, "");
+  static_assert(std::is_nothrow_constructible<X_LNEDNDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<X_LNEDEDT>::value, "");
+  static_assert(!std::is_nothrow_constructible<X_LEEDEDT>::value, "");
+
+  void Run()
+  {
+    VERIFY( checkDefaultThrowConstruct<IT>() );
+    VERIFY( checkDefaultThrowConstruct<NDT>() );
+    VERIFY( checkDefaultThrowConstruct<EDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_NDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_EDT>() );
+
+    VERIFY( checkDefaultThrowConstruct<IIT>() );
+    VERIFY( checkDefaultThrowConstruct<NNDT>() );
+    VERIFY( checkDefaultThrowConstruct<EEDT>() );
+    VERIFY( checkDefaultThrowConstruct<ENDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_NNDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_EEDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_ENDT>() );
+
+    VERIFY( checkDefaultThrowConstruct<IIIT>() );
+    VERIFY( checkDefaultThrowConstruct<LNDNDT>() );
+    VERIFY( checkDefaultThrowConstruct<LNDEDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_LNEDNDT>() );
+    VERIFY( checkDefaultThrowConstruct<X_LNEDEDT>() );
+  }
+}
+namespace AllNoThrow
+{
+  static_assert(std::is_nothrow_constructible<IT, int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IT, const int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IT, int&&>::value, "");
+  static_assert(std::is_nothrow_constructible<IT, const int&&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IT, IT>::value, "");
+  static_assert(std::is_nothrow_constructible<IT, const IT &>::value, "");
+  static_assert(std::is_nothrow_constructible<IT, CIT>::value, "");
+
+  static_assert(test_trait::is_nothrow_convertible<int&, IT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<const int&, IT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<int&&, IT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<const int&&, IT>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IIT, int&, int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIT, const int&, const int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIT, int&&, int&&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIT, const int&&, const int&&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IIT, IIT>::value, "");
+  static_assert(std::is_nothrow_constructible<IIT, const IIT &>::value, "");
+  static_assert(std::is_nothrow_constructible<IIT, IIP>::value, "");
+  static_assert(std::is_nothrow_constructible<IIT, const IIP>::value, "");
+
+  static_assert(test_trait::is_nothrow_convertible<IIT, IIT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<const IIT &, IIT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<IIP, IIT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<const IIP, IIT>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IIIT, IIIT&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIIT, const IIIT &>::value, "");
+  static_assert(std::is_nothrow_constructible<IIIT, IIIT&&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIIT, const IIIT&&>::value, "");
+
+  static_assert(test_trait::is_nothrow_convertible<IIIT&, IIIT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<const IIIT &, IIIT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<IIIT&&, IIIT>::value, "");
+  static_assert(test_trait::is_nothrow_convertible<const IIIT&&, IIIT>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IIIT, int&, int&, int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIIT, const int&, const int&, int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIIT, int&&, int&&, int&>::value, "");
+  static_assert(std::is_nothrow_constructible<IIIT, const int&&, const int&&, int&>::value, "");
+}
+namespace ThrowCopyNothrowConversion
+{
+  struct A
+  {
+    A() noexcept(true)
+        {}
+
+    A(const int&) noexcept(true)
+      {}
+
+    A(const A&) noexcept(false)
+      {  throwing_ctor_called = true; }
+
+  };
+
+  typedef std::tuple<A> AT;
+  typedef std::tuple<A,A> AAT;
+  typedef std::pair<A,A> AAP;
+  typedef std::tuple<int,A> IAT;
+  typedef std::pair<int,A> IAP;
+  typedef std::tuple<A,A,A> AAAT;
+  typedef std::tuple<int,int,A> IIAT;
+
+/* one element tests */
+  static_assert(std::is_nothrow_constructible<AT,int>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,const int>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,int&>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,const int &>::value,"");
+
+  static_assert(std::is_nothrow_constructible<AT,IT>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,const IT>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,IT&>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,const IT &>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,std::tuple<int&>>::value,"");
+  static_assert(std::is_nothrow_constructible<AT,const std::tuple<int&&>>::value,"");
+
+  static_assert(test_trait::is_nothrow_convertible<int,AT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const int,AT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<int&,AT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const int &,AT>::value,"");
+
+  static_assert(test_trait::is_nothrow_convertible<IT,AT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const IT,AT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<IT&,AT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const IT &,AT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<std::tuple<int&>,AT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const std::tuple<int&&>,AT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<AT,A>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,const A>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,A&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,const A &>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<AT,AT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,const AT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,AT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,const AT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,std::tuple<A&>>::value,"");
+  static_assert(!std::is_nothrow_constructible<AT,const std::tuple<A&&>>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<A,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const A,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<A&,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const A &,AT>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<AT,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const AT,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<AT&,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const AT &,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<std::tuple<A&>,AT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const std::tuple<A&&>,AT>::value,"");
+
+/* two element tests */
+
+  static_assert(std::is_nothrow_constructible<AAT,IIT>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,const IIT>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,IIT&>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,const IIT &>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,IIP>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,const IIP>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,IIP&>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,const IIP &>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,std::tuple<int&,int&>>::value,"");
+
+  static_assert(test_trait::is_nothrow_convertible<IIT,AAT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const IIT,AAT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<IIT&,AAT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const IIT &,AAT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<IIP,AAT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const IIP,AAT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<IIP&,AAT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const IIP &,AAT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<std::tuple<int&,int&>,AAT>::value,"");
+
+
+  static_assert(!std::is_nothrow_constructible<AAT,AAT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const AAT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,AAT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const AAT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,AAP>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const AAP>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,AAP&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const AAP &>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,std::tuple<A&,A&>>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<AAT,IAT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const IAT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,IAT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const IAT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,IAP>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const IAP>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,IAP&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const IAP &>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,std::tuple<A&,int&>>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<AAT,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const AAT,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<AAT&,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const AAT &,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<AAP,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const AAP,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<AAP&,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const AAP &,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<std::tuple<A&,A&>,AAT>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<IAT,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IAT,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IAT&,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IAT &,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IAP,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IAP,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IAP&,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IAP &,AAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<std::tuple<A&,int&>,AAT>::value,"");
+
+
+  static_assert(std::is_nothrow_constructible<AAT,int&,const int&>::value,"");
+  static_assert(std::is_nothrow_constructible<AAT,int&&,const int&&>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<AAT,A&,const A&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,A&&,const A&&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAT,const A &&,const int&&>::value,"");
+
+/* three element tests */
+  static_assert(std::is_nothrow_constructible<AAAT,IIIT>::value,"");
+  static_assert(std::is_nothrow_constructible<AAAT,const IIIT>::value,"");
+  static_assert(std::is_nothrow_constructible<AAAT,IIIT&>::value,"");
+  static_assert(std::is_nothrow_constructible<AAAT,const IIIT &>::value,"");
+
+  static_assert(test_trait::is_nothrow_convertible<IIIT,AAAT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const IIIT,AAAT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<IIIT&,AAAT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const IIIT &,AAAT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<AAAT,IIAT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAAT,const IIAT>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAAT,IIAT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAAT,const IIAT &>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<IIAT,AAAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIAT,AAAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IIAT&,AAAT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIAT &,AAAT>::value,"");
+
+  static_assert(std::is_nothrow_constructible<AAAT,int&,const int&,int&&>::value,"");
+  static_assert(!std::is_nothrow_constructible<AAAT,int &,const A &&,const int&&>::value,"");
+
+  void Run()
+  {
+    VERIFY( (checkCopyThrowConstruct<AT,int>()) );
+    VERIFY( (checkMoveThrowConstruct<AT,int>()) );
+    VERIFY( (checkCopyThrowConstruct<AT,A>()) );
+    VERIFY( (checkMoveThrowConstruct<AT,A>()) );
+    VERIFY( (checkCopyThrowConstruct<AT,AT>()) );
+    VERIFY( (checkMoveThrowConstruct<AT,AT>()) );
+    VERIFY( (checkCopyThrowConstruct<AT,IT>()) );
+    VERIFY( (checkMoveThrowConstruct<AT,IT>()) );
+    VERIFY( (checkMoveThrowConstruct<AT,CIT>()) );
+    VERIFY( (checkCopyThrowConstruct<AAT,AAT>()) );
+    VERIFY( (checkMoveThrowConstruct<AAT,AAT>()) );
+    VERIFY( (checkCopyThrowConstruct<AAT,IIT>()) );
+    VERIFY( (checkMoveThrowConstruct<AAT,IIT>()) );
+    VERIFY( (checkCopyThrowConstruct<AAT,IIP>()) );
+    VERIFY( (checkMoveThrowConstruct<AAT,IIP>()) );
+
+    VERIFY( (checkCopyThrowConstruct<AAT,std::tuple<int,A>>()) );
+    VERIFY( (checkMoveThrowConstruct<AAT,std::tuple<int,A>>()) );
+    VERIFY( (checkCopyThrowConstruct<AAT,std::pair<int,A>>()) );
+    VERIFY( (checkMoveThrowConstruct<AAT,std::pair<int,A>>()) );
+
+    VERIFY( (checkCopyThrowConstruct<AAAT,AAAT>()) );
+    VERIFY( (checkMoveThrowConstruct<AAAT,AAAT>()) );
+    VERIFY( (checkCopyThrowConstruct<AAAT,IIAT>()) );
+    VERIFY( (checkMoveThrowConstruct<AAAT,IIAT>()) );
+  }
+}
+namespace NothrowCopyThrowMoveThrowCopyConversionNothrowMoveConversion
+{
+  struct B
+  {
+    B() noexcept(true)
+        {}
+
+    B(const int&) noexcept(false)
+      {  throwing_ctor_called = true; }
+
+    B(int&&) noexcept(true)
+      {}
+
+    B(const B&) noexcept(true)
+      {}
+
+    B(B&&) noexcept(false)
+      {  throwing_ctor_called = true; }
+  };
+
+
+  struct D
+  {
+    D() noexcept(true)
+        {}
+
+    explicit
+    D(const int&) noexcept(false)
+    {  throwing_ctor_called = true; }
+
+    explicit
+    D(int&&) noexcept(true)
+        {}
+
+    explicit
+    D(const D&) noexcept(true)
+      {}
+
+    explicit
+    D(D&&) noexcept(false)
+    {  throwing_ctor_called = true; }
+
+  };
+
+  typedef std::tuple<B> BT;
+  typedef std::tuple<B,B> BBT;
+  typedef std::pair<B,B> BBP;
+  typedef std::tuple<D> DT;
+  typedef std::tuple<D,D> DDT;
+  typedef std::pair<D,D> DDP;
+  typedef std::tuple<int,D> IDT;
+  typedef std::pair<int,D> IDP;
+  typedef std::tuple<int,B> IBT;
+  typedef std::pair<int,B> IBP;
+  typedef std::tuple<D,B> DBT;
+  typedef std::pair<D,B> DBP;
+  typedef std::tuple<B,B,B> BBBT;
+  typedef std::tuple<D,D,D> DDDT;
+  typedef std::tuple<int,D,int> IDIT;
+  typedef std::tuple<int,B,int> IBIT;
+  typedef std::tuple<int,D,B> IDBT;
+
+/* one element tests */
+  static_assert(std::is_nothrow_constructible<BT, int>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, const int>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, int&>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, const int &>::value, "");
+
+  static_assert(std::is_nothrow_constructible<BT, IT>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT,const IT>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, IT&>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, const IT &>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, std::tuple<int&>>::value, "");
+  static_assert(!std::is_nothrow_constructible<BT, const std::tuple<int&&>>::value, "");
+
+  static_assert(test_trait::is_nothrow_convertible<int,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const int,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<int&,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const int &,BT>::value,"");
+
+  static_assert(test_trait::is_nothrow_convertible<IT,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IT,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IT&,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IT &,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<std::tuple<int&>,BT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const std::tuple<int&&>,BT>::value,"");
+
+
+  static_assert(!std::is_nothrow_constructible<BT, B>::value, "");
+  static_assert(std::is_nothrow_constructible<BT,const B>::value, "");
+  static_assert(std::is_nothrow_constructible<BT, B&>::value, "");
+  static_assert(std::is_nothrow_constructible<BT, const B &>::value, "");
+
+  static_assert(!std::is_nothrow_constructible<BT, BT>::value, "");
+  static_assert(std::is_nothrow_constructible<BT,const BT>::value, "");
+  static_assert(std::is_nothrow_constructible<BT, BT&>::value, "");
+  static_assert(std::is_nothrow_constructible<BT, const BT &>::value, "");
+  static_assert(std::is_nothrow_constructible<BT, std::tuple<B&>>::value, "");
+  static_assert(std::is_nothrow_constructible<BT, const std::tuple<B&&>>::value, "");
+
+  static_assert(!test_trait::is_nothrow_convertible<B,BT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const B,BT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<B&,BT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const B &,BT>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<BT,BT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const BT,BT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<BT&,BT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const BT &,BT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<std::tuple<B&>,BT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const std::tuple<B&&>,BT>::value,"");
+
+/* explicit */
+  static_assert(std::is_nothrow_constructible<DT, int>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, const int>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, int&>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, const int &>::value, "");
+
+  static_assert(std::is_nothrow_constructible<DT, IT>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT,const IT>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, IT&>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, const IT &>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, std::tuple<int&>>::value, "");
+  static_assert(!std::is_nothrow_constructible<DT, const std::tuple<int&&>>::value, "");
+
+  static_assert(!std::is_nothrow_constructible<DT, D>::value, "");
+  static_assert(std::is_nothrow_constructible<DT,const D>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, D&>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const D &>::value, "");
+
+  static_assert(!std::is_nothrow_constructible<DT, DT>::value, "");
+  static_assert(std::is_nothrow_constructible<DT,const DT>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, DT&>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const DT &>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, std::tuple<D&>>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const std::tuple<D&&>>::value, "");
+
+  static_assert(!test_trait::is_nothrow_convertible<DT,DT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const DT,DT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<DT&,DT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const DT &,DT>::value,"");
+
+/* two elements tests */
+  static_assert(std::is_nothrow_constructible<BBT,IIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,IIT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IIT &>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,IIP>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IIP>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,IIP&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IIP &>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,std::tuple<int&,int&>>::value,"");
+
+  static_assert(test_trait::is_nothrow_convertible<IIT,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIT,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IIT&,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIT &,BBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<IIP,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIP,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IIP&,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIP &,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<std::tuple<int&,int&>,BBT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<BBT,BBT>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,const BBT>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,BBT&>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,const BBT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,BBP>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,const BBP>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,BBP&>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,const BBP &>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,std::tuple<B&,B&>>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<BBT,IBT>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IBT>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,IBT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IBT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,IBP>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IBP>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,IBP&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const IBP &>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,std::tuple<const B&,int&&>>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<BBT,BBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const BBT,BBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<BBT&,BBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const BBT &,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<BBP,BBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const BBP,BBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<BBP&,BBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const BBP &,BBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<std::tuple<B&,int&&>,BBT>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<IBT,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IBT,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IBT&,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IBT &,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IBP,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IBP,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IBP&,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IBP &,BBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<std::tuple<B&,int&>,BBT>::value,"");
+
+
+  static_assert(!std::is_nothrow_constructible<BBT,int&,const int&>::value,"");
+  static_assert(std::is_nothrow_constructible<BBT,int&&,const B&>::value,"");
+
+  static_assert(std::is_nothrow_constructible<BBT,B&,const B&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,B&&,const B&&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBT,const B &&,const int&&>::value,"");
+
+/* explicit */
+  static_assert(std::is_nothrow_constructible<DDT,IIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,IIT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IIT &>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,IIP>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IIP>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,IIP&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IIP &>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,std::tuple<int&,int&>>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<DDT,DDT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const DDT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,DDT&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const DDT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,DDP>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const DDP>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,DDP&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const DDP &>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,std::tuple<D&,D&>>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<DDT,IDT>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IDT>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,IDT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IDT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,IDP>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IDP>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,IDP&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const IDP &>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,std::tuple<const D&,int&&>>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<DDT,DDT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const DDT,DDT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<DDT&,DDT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const DDT &,DDT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<DDT,int&,const int&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,int&&,const D&>::value,"");
+
+  static_assert(std::is_nothrow_constructible<DDT,D&,const D&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,D&&,const D&&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,const D &&,const int&&>::value,"");
+
+/* three elements tests */
+  static_assert(std::is_nothrow_constructible<BBBT,IIIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBBT,const IIIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBBT,IIIT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBBT,const IIIT &>::value,"");
+
+  static_assert(test_trait::is_nothrow_convertible<IIIT,BBBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIIT,BBBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<IIIT&,BBBT>::value,"");
+  static_assert(!test_trait::is_nothrow_convertible<const IIIT &,BBBT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<BBBT,BBBT>::value,"");
+  static_assert(std::is_nothrow_constructible<BBBT,const BBBT>::value,"");
+  static_assert(std::is_nothrow_constructible<BBBT,BBBT&>::value,"");
+  static_assert(std::is_nothrow_constructible<BBBT,const BBBT &>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<BBBT,BBBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const BBBT,BBBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<BBBT&,BBBT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const BBBT &,BBBT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<BBBT,int&,const int&,int&&>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBBT,int&, B&&,const int&&>::value,"");
+  static_assert(std::is_nothrow_constructible<BBBT,int&&, B&,const B&&>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<BBBT,std::tuple<int&,const int&,int&&>>::value,"");
+  static_assert(!std::is_nothrow_constructible<BBBT,std::tuple<int &, B&&,const int&&>>::value,"");
+  static_assert(std::is_nothrow_constructible<BBBT,std::tuple<int &&, B&,const B&&>>::value,"");
+
+/* explicit */
+  static_assert(std::is_nothrow_constructible<DDDT,IIIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDDT,const IIIT>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDDT,IIIT&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDDT,const IIIT &>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<DDDT,DDDT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDDT,const DDDT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDDT,DDDT&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDDT,const DDDT &>::value,"");
+
+  static_assert(!test_trait::is_nothrow_convertible<DDDT,DDDT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const DDDT,DDDT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<DDDT&,DDDT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<const DDDT &,DDDT>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<DDDT,int&,const int&,int&&>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDDT,int &, D&&,const int&&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDDT,int &&, D&,const D&&>::value,"");
+
+  static_assert(!std::is_nothrow_constructible<DDDT,std::tuple<int&,const int&,int&&>>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDDT,std::tuple<int &, D&&,const int&&>>::value,"");
+  static_assert(std::is_nothrow_constructible<DDDT,std::tuple<int &&, D&,const D&&>>::value,"");
+
+
+  void Run()
+  {
+    VERIFY( (checkCopyThrowConstruct<BT, int>()) );
+    VERIFY( (checkMoveThrowConstruct<BT, int>()) );
+    VERIFY( (checkCopyThrowConstruct<BT, B>()) );
+    VERIFY( (checkMoveThrowConstruct<BT, B>()) );
+    VERIFY( (checkCopyThrowConstruct<BT, IT>()) );
+    VERIFY( (checkMoveThrowConstruct<BT, IT>()) );
+    VERIFY( (checkMoveThrowConstruct<BT, CIT>()) );
+    VERIFY( (checkCopyThrowConstruct<BBT, IIT>()) );
+    VERIFY( (checkMoveThrowConstruct<BBT, IIT>()) );
+    VERIFY( (checkCopyThrowConstruct<BBT, IIP>()) );
+    VERIFY( (checkMoveThrowConstruct<BBT, IIP>()) );
+    VERIFY( (checkCopyThrowConstruct<BBT, BBP>()) );
+    VERIFY( (checkMoveThrowConstruct<BBT, BBP>()) );
+    VERIFY( (checkCopyThrowConstruct<BBT, std::tuple<B, int>>()) );
+    VERIFY( (checkMoveThrowConstruct<BBT, std::tuple<B, int>>()) );
+
+    VERIFY( (checkCopyThrowConstruct<DT, int>()) );
+    VERIFY( (checkMoveThrowConstruct<DT, int>()) );
+    VERIFY( (checkCopyThrowConstruct<DT, D>()) );
+    VERIFY( (checkMoveThrowConstruct<DT, D>()) );
+    VERIFY( (checkCopyThrowConstruct<DT, IT>()) );
+    VERIFY( (checkMoveThrowConstruct<DT, IT>()) );
+    VERIFY( (checkMoveThrowConstruct<DT, CIT>()) );
+    VERIFY( (checkCopyThrowConstruct<DDT, IIT>()) );
+    VERIFY( (checkMoveThrowConstruct<DDT, IIT>()) );
+    VERIFY( (checkCopyThrowConstruct<DDT, IIP>()) );
+    VERIFY( (checkMoveThrowConstruct<DDT, IIP>()) );
+    VERIFY( (checkCopyThrowConstruct<DDT, DDP>()) );
+    VERIFY( (checkMoveThrowConstruct<DDT, DDP>()) );
+    VERIFY( (checkCopyThrowConstruct<DDT, std::tuple<D, int>>()) );
+    VERIFY( (checkMoveThrowConstruct<DDT, std::tuple<D, int>>()) );
+
+    VERIFY( (checkCopyThrowConstruct<DBT, IIT>()) );
+    VERIFY( (checkMoveThrowConstruct<DBT, IIT>()) );
+    VERIFY( (checkCopyThrowConstruct<DBT, DBT>()) );
+    VERIFY( (checkMoveThrowConstruct<DBT, DBT>()) );
+    VERIFY( (checkCopyThrowConstruct<DBT, DBP>()) );
+    VERIFY( (checkMoveThrowConstruct<DBT, DBP>()) );
+    VERIFY( (checkCopyThrowConstruct<DBT, IIP>()) );
+    VERIFY( (checkMoveThrowConstruct<DBT, IIP>()) );
+
+
+    VERIFY( (checkCopyThrowConstruct<IDIT, IIIT>()) );
+    VERIFY( (checkMoveThrowConstruct<IDIT, IIIT>()) );
+    VERIFY( (checkCopyThrowConstruct<IDIT, IDIT>()) );
+    VERIFY( (checkMoveThrowConstruct<IDIT, IDIT>()) );
+    VERIFY( (checkCopyThrowConstruct<IBIT, IIIT>()) );
+    VERIFY( (checkMoveThrowConstruct<IBIT, IIIT>()) );
+    VERIFY( (checkCopyThrowConstruct<IBIT, IBIT>()) );
+    VERIFY( (checkMoveThrowConstruct<IBIT, IBIT>()) );
+    VERIFY( (checkCopyThrowConstruct<IDBT, IIIT>()) );
+    VERIFY( (checkMoveThrowConstruct<IDBT, IIIT>()) );
+    VERIFY( (checkCopyThrowConstruct<IDBT, IDBT>()) );
+    VERIFY( (checkMoveThrowConstruct<IDBT, IDBT>()) );
+
+  }
+}
+namespace ThrowCopy
+{
+  struct C
+  {
+    C() noexcept(true)
+       {}
+
+    explicit
+    C(const C&) noexcept(true) {}
+
+  };
+
+  typedef std::tuple<C> CT;
+  typedef std::tuple<C,C> CCT;
+  typedef std::pair<C,C> CCP;
+  typedef std::tuple<int,int,C> IICT;
+
+  static_assert(std::is_nothrow_constructible<CT, C&>::value, "");
+  static_assert(std::is_nothrow_constructible<CT, const C&>::value, "");
+  static_assert(std::is_nothrow_constructible<CT, C&&>::value, "");
+  static_assert(std::is_nothrow_constructible<CT, const C &&>::value, "");
+
+
+  static_assert(std::is_nothrow_constructible<CCT, C&, C&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, const C&, const C&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, C&&, C&&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, const C &&, const C &&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IICT, int, int, C&>::value, "");
+  static_assert(std::is_nothrow_constructible<IICT, int, int, const C&>::value, "");
+  static_assert(std::is_nothrow_constructible<IICT, int, int, C&&>::value, "");
+  static_assert(std::is_nothrow_constructible<IICT, int, int, const C &&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<CT, CT&>::value, "");
+  static_assert(std::is_nothrow_constructible<CT, const CT&>::value, "");
+  static_assert(std::is_nothrow_constructible<CT, CT&&>::value, "");
+  static_assert(std::is_nothrow_constructible<CT, const CT &&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<CCT, CCT&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, const CCT&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, CCT&&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, const CCT &&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<CCT, CCP&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, const CCP&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, CCP&&>::value, "");
+  static_assert(std::is_nothrow_constructible<CCT, const CCP &&>::value, "");
+
+  static_assert(std::is_nothrow_constructible<IICT, IICT&>::value, "");
+  static_assert(std::is_nothrow_constructible<IICT, const IICT&>::value, "");
+  static_assert(std::is_nothrow_constructible<IICT, IICT&&>::value, "");
+  static_assert(std::is_nothrow_constructible<IICT, const IICT &&>::value, "");
+
+}
+namespace ThrowMoveNothrowConversion
+{
+  struct D
+  {
+  D() noexcept(true)
+  {}
+
+  explicit
+  D(const int&) noexcept(true)
+  {}
+
+  explicit
+  D(int&&) noexcept(false)
+  {  throwing_ctor_called = true; }
+
+  };
+
+  typedef std::tuple<D> DT;
+  typedef std::tuple<D,D> DDT;
+  typedef std::pair<D,D> DDP;
+  typedef std::tuple<int,D,int> IDIT;
+
+
+  static_assert(!std::is_nothrow_constructible<DT, int>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const int>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, int&>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const int &>::value, "");
+
+  static_assert(!std::is_nothrow_constructible<DT, IT>::value, "");
+  static_assert(std::is_nothrow_constructible<DT,const IT>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, IT&>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const IT &>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, std::tuple<int&>>::value, "");
+  static_assert(std::is_nothrow_constructible<DT, const std::tuple<int&&>>::value, "");
+
+  static_assert(test_trait::is_nothrow_convertible<DT,DT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<D,DT>::value,"");
+
+/* two elements tests */
+  static_assert(!std::is_nothrow_constructible<DDT,IIT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const IIT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,IIT&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const IIT &>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,IIP>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const IIP>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,IIP&>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,const IIP &>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,std::tuple<int&,int&>>::value,"");
+
+  static_assert(std::is_nothrow_constructible<DDT,DDT>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,DDP>::value,"");
+  static_assert(std::is_nothrow_constructible<DDT,std::tuple<int&,D>>::value,"");
+  static_assert(!std::is_nothrow_constructible<DDT,std::pair<D,int&&>>::value,"");
+
+  static_assert(std::is_convertible<DDT,DDT>::value,"");
+
+/* three elements tests */
+  static_assert(!std::is_nothrow_constructible<IDIT,IIIT>::value,"");
+  static_assert(std::is_nothrow_constructible<IDIT,const IIIT>::value,"");
+  static_assert(std::is_nothrow_constructible<IDIT,IIIT&>::value,"");
+  static_assert(std::is_nothrow_constructible<IDIT,const IIIT &>::value,"");
+
+  static_assert(test_trait::is_nothrow_convertible<IDIT,IDIT>::value,"");
+  static_assert(test_trait::is_nothrow_convertible<IDIT,IDIT>::value,"");
+
+  static_assert(std::is_nothrow_constructible<IDIT,int&,const int&,int&&>::value,"");
+  static_assert(std::is_nothrow_constructible<IDIT,int &, D&&,const int&&>::value,"");
+  static_assert(std::is_nothrow_constructible<IDIT,std::tuple<int&,const int&,int&&>>::value,"");
+  static_assert(!std::is_nothrow_constructible<IDIT,std::tuple<int &, int&&,const int&&>>::value,"");
+
+  void Run()
+  {
+    VERIFY( (checkCopyThrowConstruct<DDT, IIT>()) );
+    VERIFY( (checkMoveThrowConstruct<DDT, IIT>()) );
+    VERIFY( (checkCopyThrowConstruct<DDT, std::tuple<D, int>>()) );
+    VERIFY( (checkMoveThrowConstruct<DDT, std::tuple<D, int>>()) );
+  }
+}
+
+int main()
+{
+
+  DefaultConstructionTests::Run();
+
+  ThrowCopyNothrowConversion::Run();
+
+  NothrowCopyThrowMoveThrowCopyConversionNothrowMoveConversion::Run();
+
+  ThrowMoveNothrowConversion::Run();
+
+}
+

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Adding noexcept-specification on tuple constructors (LWG 2899)
  2019-04-24 10:30           ` Nina Dinka Ranns
@ 2019-04-24 12:47             ` Jonathan Wakely
  2019-04-28 21:21               ` Ville Voutilainen
  0 siblings, 1 reply; 14+ messages in thread
From: Jonathan Wakely @ 2019-04-24 12:47 UTC (permalink / raw)
  To: Nina Dinka Ranns; +Cc: gcc-patches, libstdc++

On 24/04/19 11:21 +0100, Nina Dinka Ranns wrote:
>New diff attached.

Thanks, this looks great. I think we can apply this as soon as stage 1
begins (which should be Real Soon Now).


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Adding noexcept-specification on tuple constructors (LWG 2899)
  2019-04-24 12:47             ` Jonathan Wakely
@ 2019-04-28 21:21               ` Ville Voutilainen
  2019-04-28 21:44                 ` Ville Voutilainen
  2019-04-28 21:46                 ` Jonathan Wakely
  0 siblings, 2 replies; 14+ messages in thread
From: Ville Voutilainen @ 2019-04-28 21:21 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: Nina Dinka Ranns, gcc-patches List, libstdc++

On Wed, 24 Apr 2019 at 14:53, Jonathan Wakely <jwakely@redhat.com> wrote:
>
> On 24/04/19 11:21 +0100, Nina Dinka Ranns wrote:
> >New diff attached.
>
> Thanks, this looks great. I think we can apply this as soon as stage 1
> begins (which should be Real Soon Now).

Tested on Linux-PPC64, committed to trunk. Congrats, Nina, first patch
in, let there be many more. :)

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Adding noexcept-specification on tuple constructors (LWG 2899)
  2019-04-28 21:21               ` Ville Voutilainen
@ 2019-04-28 21:44                 ` Ville Voutilainen
  2019-04-28 21:46                 ` Jonathan Wakely
  1 sibling, 0 replies; 14+ messages in thread
From: Ville Voutilainen @ 2019-04-28 21:44 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: Nina Dinka Ranns, gcc-patches List, libstdc++

On Mon, 29 Apr 2019 at 00:18, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
>
> On Wed, 24 Apr 2019 at 14:53, Jonathan Wakely <jwakely@redhat.com> wrote:
> >
> > On 24/04/19 11:21 +0100, Nina Dinka Ranns wrote:
> > >New diff attached.
> >
> > Thanks, this looks great. I think we can apply this as soon as stage 1
> > begins (which should be Real Soon Now).
>
> Tested on Linux-PPC64, committed to trunk. Congrats, Nina, first patch
> in, let there be many more. :)

And as I was corrected, this was the second patch, but that doesn't
change the suggestion that there should
be many more. :P

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Adding noexcept-specification on tuple constructors (LWG 2899)
  2019-04-28 21:21               ` Ville Voutilainen
  2019-04-28 21:44                 ` Ville Voutilainen
@ 2019-04-28 21:46                 ` Jonathan Wakely
  2019-04-29  4:11                   ` Jonathan Wakely
  1 sibling, 1 reply; 14+ messages in thread
From: Jonathan Wakely @ 2019-04-28 21:46 UTC (permalink / raw)
  To: Ville Voutilainen; +Cc: Nina Dinka Ranns, gcc-patches List, libstdc++

On 29/04/19 00:18 +0300, Ville Voutilainen wrote:
>On Wed, 24 Apr 2019 at 14:53, Jonathan Wakely <jwakely@redhat.com> wrote:
>>
>> On 24/04/19 11:21 +0100, Nina Dinka Ranns wrote:
>> >New diff attached.
>>
>> Thanks, this looks great. I think we can apply this as soon as stage 1
>> begins (which should be Real Soon Now).
>
>Tested on Linux-PPC64, committed to trunk. Congrats, Nina, first patch
>in, let there be many more. :)

Thanks, Nina, and Ville for taking care of the commit.

Apologies for not noticing it earlier, but the first line of the
ChangeLog entry was not formatted correctly. There should be two
spaces either side of the author's name:

2019-04-28  John Doe  <jdoe@example.com>

not:

2019-04-28 John Doe <jdoe@example.com>

I've committed r270633 to fix it.

Thanks again.



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Adding noexcept-specification on tuple constructors (LWG 2899)
  2019-04-28 21:46                 ` Jonathan Wakely
@ 2019-04-29  4:11                   ` Jonathan Wakely
  2019-04-29 11:33                     ` Nina Dinka Ranns
  0 siblings, 1 reply; 14+ messages in thread
From: Jonathan Wakely @ 2019-04-29  4:11 UTC (permalink / raw)
  To: Ville Voutilainen; +Cc: Nina Dinka Ranns, gcc-patches List, libstdc++

On 28/04/19 22:44 +0100, Jonathan Wakely wrote:
>On 29/04/19 00:18 +0300, Ville Voutilainen wrote:
>>On Wed, 24 Apr 2019 at 14:53, Jonathan Wakely <jwakely@redhat.com> wrote:
>>>
>>>On 24/04/19 11:21 +0100, Nina Dinka Ranns wrote:
>>>>New diff attached.
>>>
>>>Thanks, this looks great. I think we can apply this as soon as stage 1
>>>begins (which should be Real Soon Now).
>>
>>Tested on Linux-PPC64, committed to trunk. Congrats, Nina, first patch
>>in, let there be many more. :)
>
>Thanks, Nina, and Ville for taking care of the commit.
>
>Apologies for not noticing it earlier, but the first line of the
>ChangeLog entry was not formatted correctly. There should be two
>spaces either side of the author's name:
>
>2019-04-28  John Doe  <jdoe@example.com>
>
>not:
>
>2019-04-28 John Doe <jdoe@example.com>
>
>I've committed r270633 to fix it.
>
>Thanks again.

Oh, and the files in the ChangeLog entry should use paths relative to
the ChangeLog file, so no libstdc++-v3/ prefixes. I missed that in the
review too.


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Adding noexcept-specification on tuple constructors (LWG 2899)
  2019-04-29  4:11                   ` Jonathan Wakely
@ 2019-04-29 11:33                     ` Nina Dinka Ranns
  0 siblings, 0 replies; 14+ messages in thread
From: Nina Dinka Ranns @ 2019-04-29 11:33 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: Ville Voutilainen, gcc-patches List, libstdc++

noted, thanks :)
Best,
Nina

On Sun, 28 Apr 2019 at 22:46, Jonathan Wakely <jwakely@redhat.com> wrote:
>
> On 28/04/19 22:44 +0100, Jonathan Wakely wrote:
> >On 29/04/19 00:18 +0300, Ville Voutilainen wrote:
> >>On Wed, 24 Apr 2019 at 14:53, Jonathan Wakely <jwakely@redhat.com> wrote:
> >>>
> >>>On 24/04/19 11:21 +0100, Nina Dinka Ranns wrote:
> >>>>New diff attached.
> >>>
> >>>Thanks, this looks great. I think we can apply this as soon as stage 1
> >>>begins (which should be Real Soon Now).
> >>
> >>Tested on Linux-PPC64, committed to trunk. Congrats, Nina, first patch
> >>in, let there be many more. :)
> >
> >Thanks, Nina, and Ville for taking care of the commit.
> >
> >Apologies for not noticing it earlier, but the first line of the
> >ChangeLog entry was not formatted correctly. There should be two
> >spaces either side of the author's name:
> >
> >2019-04-28  John Doe  <jdoe@example.com>
> >
> >not:
> >
> >2019-04-28 John Doe <jdoe@example.com>
> >
> >I've committed r270633 to fix it.
> >
> >Thanks again.
>
> Oh, and the files in the ChangeLog entry should use paths relative to
> the ChangeLog file, so no libstdc++-v3/ prefixes. I missed that in the
> review too.
>
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2019-04-29 11:09 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-16 13:28 Adding noexcept-specification on tuple constructors (LWG 2899) Nina Dinka Ranns
2019-04-16 14:25 ` Jonathan Wakely
2019-04-16 15:24   ` Ville Voutilainen
2019-04-16 17:06   ` Nina Dinka Ranns
2019-04-18 20:43     ` Jonathan Wakely
2019-04-23 19:12       ` Nina Dinka Ranns
2019-04-23 21:05         ` Jonathan Wakely
2019-04-24 10:30           ` Nina Dinka Ranns
2019-04-24 12:47             ` Jonathan Wakely
2019-04-28 21:21               ` Ville Voutilainen
2019-04-28 21:44                 ` Ville Voutilainen
2019-04-28 21:46                 ` Jonathan Wakely
2019-04-29  4:11                   ` Jonathan Wakely
2019-04-29 11:33                     ` Nina Dinka Ranns

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).