[v3 PATCH] Make the default constructors of tuple and pair conditionally explicit.

Ville Voutilainen ville.voutilainen@gmail.com
Sun Nov 1 03:27:00 GMT 2015


In the last meeting, while processing LWG 2510, LWG's guidance
was to make the default constructors of pair and tuple conditionally
explicit. This patch implements a new trait and uses it in pair and tuple.

Paolo, Jonathan is traveling and somewhat unlikely to be able to review
this for quite some time, could you please review this patch?

Tested on Linux-PPC64.

2015-11-01  Ville Voutilainen  <ville.voutilainen@gmail.com>

    Make the default constructors of tuple and pair conditionally explicit.
    * include/std/type_traits (
    __do_is_implicitly_default_constructible_impl
    __is_implicitly_default_constructible_impl,
    __is_implicitly_default_constructible_safe,
    __is_implicitly_default_constructible): New.
    * include/bits/stl_pair.h (pair::pair()): Use it.
    * include/std/tuple (tuple<_T1, _T2>::tuple): Use it.
    * include/std/tuple (ImplicitlyDefaultConstructibleTuple): New.
    * include/std/tuple (tuple<_Types...>::tuple()): Use it.
    * testsuite/20_util/declval/requirements/1_neg.cc: Adjust.
    * testsuite/20_util/is_implicitly_default_constructible/requirements/explicit_instantiation.cc:
New.
    * testsuite/20_util/is_implicitly_default_constructible/requirements/typedefs.cc:
Likewise.
    * testsuite/20_util/is_implicitly_default_constructible/value.cc: Likewise.
    * testsuite/20_util/make_signed/requirements/typedefs_neg.cc: Adjust.
    * testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc: Likewise.
    * testsuite/20_util/pair/cons/explicit_construct.cc: Likewise.
    * testsuite/20_util/tuple/cons/explicit_construct.cc: Likewise.
-------------- next part --------------
diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h
index a5a7898..dfcd357 100644
--- a/libstdc++-v3/include/bits/stl_pair.h
+++ b/libstdc++-v3/include/bits/stl_pair.h
@@ -141,13 +141,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       template <typename _U1 = _T1,
                 typename _U2 = _T2,
                 typename enable_if<__and_<
-                                     is_default_constructible<_U1>,
-                                     is_default_constructible<_U2>>
+                                     __is_implicitly_default_constructible<_U1>,
+                                     __is_implicitly_default_constructible<_U2>>
                                    ::value, bool>::type = true>
 #endif
       _GLIBCXX_CONSTEXPR pair()
       : first(), second() { }
 
+#if __cplusplus >= 201103L
+      template <typename _U1 = _T1,
+                typename _U2 = _T2,
+                typename enable_if<__and_<
+                       is_default_constructible<_U1>,
+                       is_default_constructible<_U2>,
+                       __not_<
+                         __and_<__is_implicitly_default_constructible<_U1>,
+                                __is_implicitly_default_constructible<_U2>>>>
+                                   ::value, bool>::type = false>
+      explicit constexpr pair()
+      : first(), second() { }
+#endif
+
       /** Two objects may be passed to a @c pair constructor to be copied.  */
 #if __cplusplus < 201103L
       pair(const _T1& __a, const _T2& __b)
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index 8af01f4..e6c32b3 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -551,16 +551,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         {
           return __and_<is_default_constructible<_Elements>...>::value;
         }
+        static constexpr bool _ImplicitlyDefaultConstructibleTuple()
+        {
+          return __and_<__is_implicitly_default_constructible<_Elements>...>
+            ::value;
+        }
       };
 
     public:
       template<typename _Dummy = void,
                typename enable_if<_TC2<_Dummy>::
-                                    _DefaultConstructibleTuple(),
+                                    _ImplicitlyDefaultConstructibleTuple(),
                                   bool>::type = true>
       constexpr tuple()
       : _Inherited() { }
 
+      template<typename _Dummy = void,
+               typename enable_if<_TC2<_Dummy>::
+                                    _DefaultConstructibleTuple()
+                                  &&
+                                  !_TC2<_Dummy>::
+                                    _ImplicitlyDefaultConstructibleTuple(),
+                                  bool>::type = false>
+      explicit constexpr tuple()
+      : _Inherited() { }
+
       // Shortcut for the cases where constructors taking _Elements...
       // need to be constrained.
       template<typename _Dummy> using _TCC =
@@ -837,13 +852,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       template <typename _U1 = _T1,
                 typename _U2 = _T2,
                 typename enable_if<__and_<
-                                     is_default_constructible<_U1>,
-                                     is_default_constructible<_U2>>
+                                     __is_implicitly_default_constructible<_U1>,
+                                     __is_implicitly_default_constructible<_U2>>
                                    ::value, bool>::type = true>
 
       constexpr tuple()
       : _Inherited() { }
 
+      template <typename _U1 = _T1,
+                typename _U2 = _T2,
+                typename enable_if<
+                  __and_<
+                    is_default_constructible<_U1>,
+                    is_default_constructible<_U2>,
+                    __not_<
+                      __and_<__is_implicitly_default_constructible<_U1>,
+                             __is_implicitly_default_constructible<_U2>>>>
+                  ::value, bool>::type = false>
+
+      explicit constexpr tuple()
+      : _Inherited() { }
+
       // Shortcut for the cases where constructors taking _T1, _T2
       // need to be constrained.
       template<typename _Dummy> using _TCC =
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index e08131b..bc68be5 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -1337,6 +1337,37 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     : public is_trivially_constructible<_Tp>::type
     { };
 
+  struct __do_is_implicitly_default_constructible_impl
+  {
+    template <typename _Tp>
+    static void __helper(const _Tp&);
+
+    template <typename _Tp>
+    static true_type __test(const _Tp&,
+                            decltype(__helper<const _Tp&>({}))* = 0);
+
+    static false_type __test(...);
+  };
+
+  template<typename _Tp>
+    struct __is_implicitly_default_constructible_impl
+      : public __do_is_implicitly_default_constructible_impl
+  {
+    typedef decltype(__test(declval<_Tp>())) type;
+  };
+
+  template<typename _Tp>
+    struct __is_implicitly_default_constructible_safe
+      : public __is_implicitly_default_constructible_impl<_Tp>::type
+  { };
+
+  template <typename _Tp>
+    struct __is_implicitly_default_constructible
+      : public integral_constant<bool,
+                    (is_default_constructible<_Tp>::value
+                    && __is_implicitly_default_constructible_safe<_Tp>::value)>
+  { };
+
   /// is_trivially_copy_constructible
   template<typename _Tp>
     struct is_trivially_copy_constructible
diff --git a/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc b/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc
index 2723e5c..ff7d9ff 100644
--- a/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc
@@ -19,7 +19,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-error "static assertion failed" "" { target *-*-* } 2209 }
+// { dg-error "static assertion failed" "" { target *-*-* } 2240 }
 
 #include <utility>
 
diff --git a/libstdc++-v3/testsuite/20_util/is_implicitly_default_constructible/requirements/explicit_instantiation.cc b/libstdc++-v3/testsuite/20_util/is_implicitly_default_constructible/requirements/explicit_instantiation.cc
new file mode 100644
index 0000000..acc9f37
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_implicitly_default_constructible/requirements/explicit_instantiation.cc
@@ -0,0 +1,27 @@
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+// Copyright (C) 2015 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <type_traits>
+
+namespace std
+{
+  typedef short test_type;
+  template struct std::__is_implicitly_default_constructible<test_type>;
+}
diff --git a/libstdc++-v3/testsuite/20_util/is_implicitly_default_constructible/requirements/typedefs.cc b/libstdc++-v3/testsuite/20_util/is_implicitly_default_constructible/requirements/typedefs.cc
new file mode 100644
index 0000000..234b06c
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_implicitly_default_constructible/requirements/typedefs.cc
@@ -0,0 +1,32 @@
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+// Copyright (C) 2015 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <type_traits>
+
+
+void test01()
+{
+  // Check for required typedefs
+  typedef std::__is_implicitly_default_constructible<int>          test_type;
+  typedef test_type::value_type                     value_type;
+  typedef test_type::type                           type;
+  typedef test_type::type::value_type               type_value_type;
+  typedef test_type::type::type                     type_type;
+}
diff --git a/libstdc++-v3/testsuite/20_util/is_implicitly_default_constructible/value.cc b/libstdc++-v3/testsuite/20_util/is_implicitly_default_constructible/value.cc
new file mode 100644
index 0000000..aff4955
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_implicitly_default_constructible/value.cc
@@ -0,0 +1,44 @@
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+// Copyright (C) 2015 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <type_traits>
+
+struct ExplicitDefault
+{
+  explicit ExplicitDefault() {}
+};
+
+struct ExplicitDefaultDefault
+{
+  explicit ExplicitDefaultDefault() = default;
+};
+
+void test01()
+{
+  using std::__is_implicitly_default_constructible;
+  // Positive tests.
+  static_assert(__is_implicitly_default_constructible<int>::value, "");
+  // Negative tests.
+  static_assert(!__is_implicitly_default_constructible<int&>::value, "");
+  static_assert(!__is_implicitly_default_constructible<
+                ExplicitDefault>::value, "");
+  static_assert(!__is_implicitly_default_constructible<
+                ExplicitDefaultDefault>::value, "");
+}
diff --git a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc
index 507930d..e06cb99 100644
--- a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc
@@ -48,4 +48,4 @@ void test01()
 // { dg-error "required from here" "" { target *-*-* } 40 }
 // { dg-error "required from here" "" { target *-*-* } 42 }
 
-// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1874 }
+// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1905 }
diff --git a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc
index 608fd1a..21335ce 100644
--- a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc
@@ -48,5 +48,5 @@ void test01()
 // { dg-error "required from here" "" { target *-*-* } 40 }
 // { dg-error "required from here" "" { target *-*-* } 42 }
 
-// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1770 }
-// { dg-error "declaration of" "" { target *-*-* } 1727 }
+// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1801 }
+// { dg-error "declaration of" "" { target *-*-* } 1758 }
diff --git a/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc b/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc
index 50edda9..ac1dc7e 100644
--- a/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc
+++ b/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc
@@ -26,6 +26,16 @@ struct Explicit
   explicit Explicit(int) {}
 };
 
+struct ExplicitDefault
+{
+  explicit ExplicitDefault() {}
+};
+
+struct ExplicitDefaultDefault
+{
+  explicit ExplicitDefaultDefault() = default;
+};
+
 std::pair<int, int> f1() {return {1,2};}
 
 std::pair<Explicit, Explicit> f2() {return {1,2};} // { dg-error "explicit" }
@@ -72,6 +82,20 @@ void f6(std::pair<Explicit, Explicit>) {}
 
 void f7(std::pair<long, long>) {}
 
+std::pair<ExplicitDefault, int> f8()
+{
+  return {}; // { dg-error "explicit" }
+}
+
+std::pair<ExplicitDefaultDefault, int> f9()
+{
+  return {}; // { dg-error "explicit" }
+}
+
+void f10(std::pair<ExplicitDefault, int>) {}
+
+void f11(std::pair<ExplicitDefaultDefault, int>) {}
+
 void test_arg_passing()
 {
   f6(v0); // { dg-error "could not convert" }
@@ -84,6 +108,10 @@ void test_arg_passing()
   f7({1,2});
   f7(std::pair<int, int>{});
   f7(std::pair<long, long>{});
+  f10({}); // { dg-error "explicit" }
+  f11({}); // { dg-error "explicit" }
+  f10(std::pair<ExplicitDefault, int>{});
+  f11(std::pair<ExplicitDefaultDefault, int>{});
 }
 
 struct MoveOnly
diff --git a/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc b/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc
index 114a490..4d97cfb 100644
--- a/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc
+++ b/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc
@@ -28,13 +28,26 @@ struct Explicit
   explicit Explicit(int) {}
 };
 
+struct ExplicitDefault
+{
+  explicit ExplicitDefault() {}
+};
+
+struct ExplicitDefaultDefault
+{
+  explicit ExplicitDefaultDefault() = default;
+};
+
 std::tuple<int> f1a() {return {1};}
 std::tuple<int, int> f1b() {return {1,2};}
 std::tuple<int, int, int> f1c() {return {1,2,3};}
 
-std::tuple<Explicit> f2_a() {return {1};} // { dg-error "explicit" }
-std::tuple<Explicit, Explicit> f2_b() {return {1,2};} // { dg-error "explicit" }
-std::tuple<Explicit, Explicit, Explicit> f2_c() {return {1,2,3};} // { dg-error "explicit" }
+std::tuple<Explicit> f2_a()
+{return {1};} // { dg-error "explicit" }
+std::tuple<Explicit, Explicit> f2_b()
+{return {1,2};} // { dg-error "explicit" }
+std::tuple<Explicit, Explicit, Explicit> f2_c()
+{return {1,2,3};} // { dg-error "explicit" }
 
 std::tuple<long> f3_a() {return std::tuple<int>{1};}
 std::tuple<long, long> f3_b() {return std::tuple<int, int>{1,2};}
@@ -57,6 +70,24 @@ std::tuple<long> f5_a() {return {1};}
 std::tuple<long, long> f5_b() {return {1,2};}
 std::tuple<long, long, long> f5_c() {return {1,2,3};}
 
+std::tuple<ExplicitDefault> f6_a()
+{return {};} // { dg-error "explicit" }
+std::tuple<ExplicitDefault, ExplicitDefault> f6_b()
+{return {};} // { dg-error "explicit" }
+std::tuple<ExplicitDefault, ExplicitDefault, ExplicitDefault> f6_c()
+{return {};} // { dg-error "explicit" }
+std::tuple<ExplicitDefault, int> f6_d()
+{return {};} // { dg-error "explicit" }
+
+std::tuple<ExplicitDefaultDefault> f7_a()
+{return {};} // { dg-error "explicit" }
+std::tuple<ExplicitDefaultDefault, ExplicitDefaultDefault> f7_b()
+{return {};} // { dg-error "explicit" }
+std::tuple<ExplicitDefaultDefault,
+           ExplicitDefaultDefault,
+           ExplicitDefaultDefault> f7_c()
+{return {};} // { dg-error "explicit" }
+
 std::tuple<int, int> fp1() {return std::pair<int, int>{1,2}; }
 std::tuple<long, long> fp2() {return std::pair<int, int>{1,2}; }
 std::tuple<Explicit, Explicit> fp3()
@@ -163,7 +194,7 @@ std::tuple<long, long, long>
   v31_c{std::allocator_arg, std::allocator<int>{}, 1,2,3};
 
 std::tuple<Explicit> v32_a
-  = {std::allocator_arg, std::allocator<int>{}, 1}; // { dg-error "explicit" }
+  = {std::allocator_arg, std::allocator<int>{ }, 1}; // { dg-error "explicit" }
 std::tuple<Explicit, Explicit> v32_b
   = {std::allocator_arg, std::allocator<int>{}, 1, 2}; // { dg-error "explicit" }
 std::tuple<Explicit, Explicit, Explicit> v32_c
@@ -199,7 +230,19 @@ std::tuple<int, int> v42 = {std::allocator_arg, std::allocator<int>{}, v20};
 std::tuple<long, long> v43 = {std::allocator_arg, std::allocator<int>{}, v20};
 
 std::tuple<Explicit, Explicit> v44
-= {std::allocator_arg, std::allocator<int>{}, v20}; // { dg-error "explicit" }
+= {std::allocator_arg, std::allocator<int>{ }, v20}; // { dg-error "explicit" }
+std::tuple<ExplicitDefault> v45_a{};
+std::tuple<ExplicitDefault, int> v45_b{};
+
+std::tuple<ExplicitDefault> v46_a = {}; // { dg-error "explicit" }
+std::tuple<ExplicitDefault, int> v46_b = {}; // { dg-error "explicit" }
+
+std::tuple<ExplicitDefaultDefault> v47_a{};
+std::tuple<ExplicitDefaultDefault, int> v47_b{};
+
+std::tuple<ExplicitDefaultDefault> v48_a = {}; // { dg-error "explicit" }
+std::tuple<ExplicitDefaultDefault, int> v48_b = { }; // { dg-error "explicit" }
+
 
 struct DeletedCopy
 {
@@ -225,58 +268,73 @@ std::tuple<int, int, Sanity> v50(std::allocator_arg,
                                  std::allocator<Sanity>{},
                                  3, 4, {42});
 
-void f6_a(std::tuple<Explicit>) {}
-void f6_b(std::tuple<Explicit, Explicit>) {}
-void f6_c(std::tuple<Explicit, Explicit, Explicit>) {}
+void f8_a(std::tuple<Explicit>) {}
+void f8_b(std::tuple<Explicit, Explicit>) {}
+void f8_c(std::tuple<Explicit, Explicit, Explicit>) {}
+
+void f9_a(std::tuple<long>) {}
+void f9_b(std::tuple<long, long>) {}
+void f9_c(std::tuple<long, long, long>) {}
+
+void f10_a(std::tuple<ExplicitDefault>) {}
+void f10_b(std::tuple<ExplicitDefault, int>) {}
 
-void f7_a(std::tuple<long>) {}
-void f7_b(std::tuple<long, long>) {}
-void f7_c(std::tuple<long, long, long>) {}
+void f11_a(std::tuple<ExplicitDefaultDefault>) {}
+void f11_b(std::tuple<ExplicitDefaultDefault, int>) {}
 
 void test_arg_passing()
 {
-  f6_a(v0_a); // { dg-error "could not convert" }
-  f6_b(v0_b); // { dg-error "could not convert" }
-  f6_c(v0_c); // { dg-error "could not convert" }
-  f6_b(v20); // { dg-error "could not convert" }
-
-  f6_a(v1_a);
-  f6_b(v1_b);
-  f6_c(v1_c);
-
-  f6_a({1}); // { dg-error "explicit" }
-  f6_b({1,2}); // { dg-error "explicit" }
-  f6_c({1,2,3}); // { dg-error "explicit" }
-
-  f6_a(std::tuple<Explicit>{});
-  f6_b(std::tuple<Explicit, Explicit>{});
-  f6_c(std::tuple<Explicit, Explicit, Explicit>{});
-
-  f6_a(std::tuple<int>{}); // { dg-error "could not convert" }
-  f6_b(std::tuple<int, int>{}); // { dg-error "could not convert" }
-  f6_c(std::tuple<int, int, int>{}); // { dg-error "could not convert" }
-  f6_b(std::pair<int, int>{}); // { dg-error "could not convert" }
-
-  f7_a(v0_a);
-  f7_b(v0_b);
-  f7_c(v0_c);
-  f7_b(v20);
-
-  f7_a(v6_a);
-  f7_b(v6_b);
-  f7_c(v6_c);
-
-  f7_a({1});
-  f7_b({1,2});
-  f7_c({1,2,3});
-
-  f7_a(std::tuple<int>{});
-  f7_b(std::tuple<int, int>{});
-  f7_c(std::tuple<int, int, int>{});
-  f7_b(std::pair<int, int>{});
-
-
-  f7_a(std::tuple<long>{});
-  f7_b(std::tuple<long, long>{});
-  f7_c(std::tuple<long, long, long>{});
+  f8_a(v0_a); // { dg-error "could not convert" }
+  f8_b(v0_b); // { dg-error "could not convert" }
+  f8_c(v0_c); // { dg-error "could not convert" }
+  f8_b(v20); // { dg-error "could not convert" }
+
+  f8_a(v1_a);
+  f8_b(v1_b);
+  f8_c(v1_c);
+
+  f8_a({1}); // { dg-error "explicit" }
+  f8_b({1,2}); // { dg-error "explicit" }
+  f8_c({1,2,3}); // { dg-error "explicit" }
+
+  f8_a(std::tuple<Explicit>{});
+  f8_b(std::tuple<Explicit, Explicit>{});
+  f8_c(std::tuple<Explicit, Explicit, Explicit>{});
+
+  f8_a(std::tuple<int>{}); // { dg-error "could not convert" }
+  f8_b(std::tuple<int, int>{}); // { dg-error "could not convert" }
+  f8_c(std::tuple<int, int, int>{}); // { dg-error "could not convert" }
+  f8_b(std::pair<int, int>{}); // { dg-error "could not convert" }
+
+  f9_a(v0_a);
+  f9_b(v0_b);
+  f9_c(v0_c);
+  f9_b(v20);
+
+  f9_a(v6_a);
+  f9_b(v6_b);
+  f9_c(v6_c);
+
+  f9_a({1});
+  f9_b({1,2});
+  f9_c({1,2,3});
+
+  f9_a(std::tuple<int>{});
+  f9_b(std::tuple<int, int>{});
+  f9_c(std::tuple<int, int, int>{});
+  f9_b(std::pair<int, int>{});
+
+  f9_a(std::tuple<long>{});
+  f9_b(std::tuple<long, long>{});
+  f9_c(std::tuple<long, long, long>{});
+
+  f10_a({}); // { dg-error "explicit" }
+  f10_b({}); // { dg-error "explicit" }
+  f11_a({}); // { dg-error "explicit" }
+  f11_b({}); // { dg-error "explicit" }
+
+  f10_a(std::tuple<ExplicitDefault>{});
+  f10_b(std::tuple<ExplicitDefault, int>{});
+  f11_a(std::tuple<ExplicitDefaultDefault>{});
+  f11_b(std::tuple<ExplicitDefaultDefault, int>{});
 }


More information about the Libstdc++ mailing list