public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [v3 PATCH] Make the default constructors of tuple and pair conditionally explicit.
@ 2015-11-01  3:27 Ville Voutilainen
  2015-11-02 15:19 ` Paolo Carlini
  0 siblings, 1 reply; 10+ messages in thread
From: Ville Voutilainen @ 2015-11-01  3:27 UTC (permalink / raw)
  To: gcc-patches, libstdc++, Paolo Carlini

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

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.

[-- Attachment #2: conditional-explicit-default-ctors-pair-tuple2.diff --]
[-- Type: text/plain, Size: 21328 bytes --]

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>{});
 }

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

* Re: [v3 PATCH] Make the default constructors of tuple and pair conditionally explicit.
  2015-11-01  3:27 [v3 PATCH] Make the default constructors of tuple and pair conditionally explicit Ville Voutilainen
@ 2015-11-02 15:19 ` Paolo Carlini
  2015-11-02 17:00   ` Ville Voutilainen
  0 siblings, 1 reply; 10+ messages in thread
From: Paolo Carlini @ 2015-11-02 15:19 UTC (permalink / raw)
  To: Ville Voutilainen, gcc-patches, libstdc++

Hi Ville,

On 11/01/2015 04:27 AM, Ville Voutilainen wrote:
> 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?
Sure, Jonathan told me a few weeks ago. Note anyway that I would not 
expect major issues with committing this kind of patch even after the 
end of Stage 1...

Anyway, so far the only detail which makes me a little nervous is the 
following:

+  template <typename _Tp>
+    struct __is_implicitly_default_constructible
+      : public integral_constant<bool,
+                    (is_default_constructible<_Tp>::value
+                    && __is_implicitly_default_constructible_safe<_Tp>::value)>


I think we want to use __and_ (note that there isn't a single logical && 
in the whole type_traits, outside macros).

Paolo.

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

* Re: [v3 PATCH] Make the default constructors of tuple and pair conditionally explicit.
  2015-11-02 15:19 ` Paolo Carlini
@ 2015-11-02 17:00   ` Ville Voutilainen
  2015-11-02 19:20     ` Paolo Carlini
  0 siblings, 1 reply; 10+ messages in thread
From: Ville Voutilainen @ 2015-11-02 17:00 UTC (permalink / raw)
  To: Paolo Carlini; +Cc: gcc-patches, libstdc++

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

On 2 November 2015 at 17:19, Paolo Carlini <paolo.carlini@oracle.com> wrote:
> Anyway, so far the only detail which makes me a little nervous is the
> following:
>
> +  template <typename _Tp>
> +    struct __is_implicitly_default_constructible
> +      : public integral_constant<bool,
> +                    (is_default_constructible<_Tp>::value
> +                    &&
> __is_implicitly_default_constructible_safe<_Tp>::value)>
>
>
> I think we want to use __and_ (note that there isn't a single logical && in
> the whole type_traits, outside macros).


Yep. New patch, tested on Linux-PPC64. Minor typo fixes for the
changelog. Ok for trunk?


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.

[-- Attachment #2: conditional-explicit-default-ctors-pair-tuple3.diff --]
[-- Type: text/plain, Size: 21364 bytes --]

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..6e11f17 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -1337,6 +1337,38 @@ _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,
+                    (__and_<is_default_constructible<_Tp>,
+                            __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..e3a33ae 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 *-*-* } 2241 }
 
 #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..3a3f6b5 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 *-*-* } 1906 }
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..79fea75 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 *-*-* } 1802 }
+// { dg-error "declaration of" "" { target *-*-* } 1759 }
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>{});
 }

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

* Re: [v3 PATCH] Make the default constructors of tuple and pair conditionally explicit.
  2015-11-02 17:00   ` Ville Voutilainen
@ 2015-11-02 19:20     ` Paolo Carlini
  2015-11-02 20:20       ` Ville Voutilainen
  0 siblings, 1 reply; 10+ messages in thread
From: Paolo Carlini @ 2015-11-02 19:20 UTC (permalink / raw)
  To: Ville Voutilainen; +Cc: gcc-patches, libstdc++

Hi,

+  template <typename _Tp>
+    struct __is_implicitly_default_constructible
+      : public integral_constant<bool,
+                    (__and_<is_default_constructible<_Tp>,
+                            __is_implicitly_default_constructible_safe<_Tp>
+                           >::value)>


Can we follow the terse style already used elsewhere (eg, 
__is_direct_constructible_new_safe) thus directly inherit from __and_ 
and avoid explicit integral_constant? Otherwise patch looks good to me.

Thanks,
Paolo.

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

* Re: [v3 PATCH] Make the default constructors of tuple and pair conditionally explicit.
  2015-11-02 19:20     ` Paolo Carlini
@ 2015-11-02 20:20       ` Ville Voutilainen
  2015-11-02 21:07         ` Paolo Carlini
  0 siblings, 1 reply; 10+ messages in thread
From: Ville Voutilainen @ 2015-11-02 20:20 UTC (permalink / raw)
  To: Paolo Carlini; +Cc: gcc-patches, libstdc++

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

On 2 November 2015 at 21:20, Paolo Carlini <paolo.carlini@oracle.com> wrote:
> Can we follow the terse style already used elsewhere (eg,
> __is_direct_constructible_new_safe) thus directly inherit from __and_ and
> avoid explicit integral_constant? Otherwise patch looks good to me.


Sure. Tested again on Linux-PPC64, tests adjusted due to line changes,
Changelog entry updated to have a correct date on it.

2015-11-02  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.

[-- Attachment #2: conditional-explicit-default-ctors-pair-tuple4.diff --]
[-- Type: text/plain, Size: 21274 bytes --]

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..ccbae87 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -1337,6 +1337,36 @@ _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 __and_<is_default_constructible<_Tp>,
+                      __is_implicitly_default_constructible_safe<_Tp>>
+  { };
+
   /// 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..4e7deda 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 *-*-* } 2239 }
 
 #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..8e5fe53 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 *-*-* } 1904 }
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..4cd0311 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 *-*-* } 1800 }
+// { dg-error "declaration of" "" { target *-*-* } 1757 }
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>{});
 }

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

* Re: [v3 PATCH] Make the default constructors of tuple and pair conditionally explicit.
  2015-11-02 20:20       ` Ville Voutilainen
@ 2015-11-02 21:07         ` Paolo Carlini
  2015-11-03  5:02           ` Ville Voutilainen
  2015-11-03 14:43           ` Jonathan Wakely
  0 siblings, 2 replies; 10+ messages in thread
From: Paolo Carlini @ 2015-11-02 21:07 UTC (permalink / raw)
  To: Ville Voutilainen; +Cc: gcc-patches, libstdc++

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

Hi,

On 11/02/2015 09:20 PM, Ville Voutilainen wrote:
> On 2 November 2015 at 21:20, Paolo Carlini <paolo.carlini@oracle.com> wrote:
>> Can we follow the terse style already used elsewhere (eg,
>> __is_direct_constructible_new_safe) thus directly inherit from __and_ and
>> avoid explicit integral_constant? Otherwise patch looks good to me.
>
> Sure. Tested again on Linux-PPC64, tests adjusted due to line changes,
> Changelog entry updated to have a correct date on it.
Great, thanks a lot. Thinking more about this detail, I wonder if we 
should therefore apply the below too? Anything I'm missing?

Paolo.

///////////////



[-- Attachment #2: p --]
[-- Type: text/plain, Size: 5415 bytes --]

Index: type_traits
===================================================================
--- type_traits	(revision 229652)
+++ type_traits	(working copy)
@@ -715,7 +715,7 @@
   /// is_unsigned
   template<typename _Tp>
     struct is_unsigned
-    : public __and_<is_arithmetic<_Tp>, __not_<is_signed<_Tp>>>::type
+    : public __and_<is_arithmetic<_Tp>, __not_<is_signed<_Tp>>>
     { };
 
 
@@ -744,7 +744,7 @@
 
   template<typename _Tp>
     struct __is_array_unknown_bounds
-    : public __and_<is_array<_Tp>, __not_<extent<_Tp>>>::type
+    : public __and_<is_array<_Tp>, __not_<extent<_Tp>>>
     { };
     
   // In N3290 is_destructible does not say anything about function
@@ -862,7 +862,7 @@
   template<typename _Tp>
     struct __is_default_constructible_atom
     : public __and_<__not_<is_void<_Tp>>,
-                    __is_default_constructible_impl<_Tp>>::type
+                    __is_default_constructible_impl<_Tp>>
     { };
 
   template<typename _Tp, bool = is_array<_Tp>::value>
@@ -877,7 +877,7 @@
     struct __is_default_constructible_safe<_Tp, true>
     : public __and_<__is_array_known_bounds<_Tp>,
 		    __is_default_constructible_atom<typename
-                      remove_all_extents<_Tp>::type>>::type
+                      remove_all_extents<_Tp>::type>>
     { };
 
   template<typename _Tp>
@@ -957,7 +957,7 @@
   template<typename _Tp, typename _Arg>
     struct __is_direct_constructible_new_safe
     : public __and_<is_destructible<_Tp>,
-                    __is_direct_constructible_impl<_Tp, _Arg>>::type
+                    __is_direct_constructible_impl<_Tp, _Arg>>
     { };
 
   template<typename, typename>
@@ -1029,7 +1029,7 @@
     : public __and_<__is_static_castable<_Arg, _Tp>,
                     __not_<__or_<__is_base_to_derived_ref<_Arg, _Tp>,
                                  __is_lvalue_to_rvalue_ref<_Arg, _Tp>
-                   >>>::type
+                   >>>
     { };
 
   template<typename _Tp, typename _Arg>
@@ -1144,7 +1144,7 @@
     struct __is_nt_default_constructible_impl<_Tp, true>
     : public __and_<__is_array_known_bounds<_Tp>,
 		    __is_nt_default_constructible_atom<typename
-                      remove_all_extents<_Tp>::type>>::type
+                      remove_all_extents<_Tp>::type>>
     { };
 
   template<typename _Tp>
@@ -1156,7 +1156,7 @@
   template<typename _Tp>
     struct is_nothrow_default_constructible
     : public __and_<is_default_constructible<_Tp>,
-                    __is_nt_default_constructible_impl<_Tp>>::type
+                    __is_nt_default_constructible_impl<_Tp>>
     { };
 
   template<typename _Tp, typename... _Args>
@@ -1179,7 +1179,7 @@
   template<typename _Tp, typename... _Args>
     struct is_nothrow_constructible
     : public __and_<is_constructible<_Tp, _Args...>,
-		    __is_nt_constructible_impl<_Tp, _Args...>>::type
+		    __is_nt_constructible_impl<_Tp, _Args...>>
     { };
 
   template<typename _Tp, bool = __is_referenceable<_Tp>::value>
@@ -1285,7 +1285,7 @@
   template<typename _Tp, typename _Up>
     struct is_nothrow_assignable
     : public __and_<is_assignable<_Tp, _Up>,
-		    __is_nt_assignable_impl<_Tp, _Up>>::type
+		    __is_nt_assignable_impl<_Tp, _Up>>
     { };
 
   template<typename _Tp, bool = __is_referenceable<_Tp>::value>
@@ -1328,7 +1328,7 @@
   template<typename _Tp, typename... _Args>
     struct is_trivially_constructible
     : public __and_<is_constructible<_Tp, _Args...>, integral_constant<bool,
-			__is_trivially_constructible(_Tp, _Args...)>>::type
+			__is_trivially_constructible(_Tp, _Args...)>>
     { };
   
   /// is_trivially_default_constructible
@@ -1342,7 +1342,7 @@
     struct is_trivially_copy_constructible
     : public __and_<is_copy_constructible<_Tp>, 
 		    integral_constant<bool,
-			__is_trivially_constructible(_Tp, const _Tp&)>>::type
+			__is_trivially_constructible(_Tp, const _Tp&)>>
     { };
   
   /// is_trivially_move_constructible
@@ -1350,7 +1350,7 @@
     struct is_trivially_move_constructible
     : public __and_<is_move_constructible<_Tp>, 
 		    integral_constant<bool,
-			__is_trivially_constructible(_Tp, _Tp&&)>>::type
+			__is_trivially_constructible(_Tp, _Tp&&)>>
     { };
 
   /// is_trivially_assignable
@@ -1358,7 +1358,7 @@
     struct is_trivially_assignable
     : public __and_<is_assignable<_Tp, _Up>, 
 		    integral_constant<bool,
-			__is_trivially_assignable(_Tp, _Up)>>::type
+			__is_trivially_assignable(_Tp, _Up)>>
     { };
 
   /// is_trivially_copy_assignable
@@ -1366,7 +1366,7 @@
     struct is_trivially_copy_assignable
     : public __and_<is_copy_assignable<_Tp>, 
 		    integral_constant<bool,
-			__is_trivially_assignable(_Tp&, const _Tp&)>>::type
+			__is_trivially_assignable(_Tp&, const _Tp&)>>
     { };
 
   /// is_trivially_move_assignable
@@ -1374,7 +1374,7 @@
     struct is_trivially_move_assignable
     : public __and_<is_move_assignable<_Tp>, 
 		    integral_constant<bool,
-			__is_trivially_assignable(_Tp&, _Tp&&)>>::type
+			__is_trivially_assignable(_Tp&, _Tp&&)>>
     { };
 
   /// is_trivially_destructible
@@ -1381,7 +1381,7 @@
   template<typename _Tp>
     struct is_trivially_destructible
     : public __and_<is_destructible<_Tp>, integral_constant<bool,
-			      __has_trivial_destructor(_Tp)>>::type
+			      __has_trivial_destructor(_Tp)>>
     { };
 
   /// has_trivial_default_constructor (temporary legacy)

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

* Re: [v3 PATCH] Make the default constructors of tuple and pair conditionally explicit.
  2015-11-02 21:07         ` Paolo Carlini
@ 2015-11-03  5:02           ` Ville Voutilainen
  2015-11-03  8:32             ` Paolo Carlini
  2015-11-03 14:43           ` Jonathan Wakely
  1 sibling, 1 reply; 10+ messages in thread
From: Ville Voutilainen @ 2015-11-03  5:02 UTC (permalink / raw)
  To: Paolo Carlini; +Cc: gcc-patches, libstdc++

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

On 2 November 2015 at 23:07, Paolo Carlini <paolo.carlini@oracle.com> wrote:
> Great, thanks a lot. Thinking more about this detail, I wonder if we should
> therefore apply the below too? Anything I'm missing?

Tested again on Linux-PPC64. Ok for trunk?

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

    Make the default constructors of tuple and pair conditionally explicit.
    * include/std/type_traits (is_unsigned, __is_array_unknown_bounds,
    __is_default_constructible_atom, __is_default_constructible_safe,
    __is_direct_constructible_new_safe, __is_direct_constructible_ref_cast,
        __is_nt_default_constructible_impl, is_nothrow_default_constructible,
        is_nothrow_constructible, is_nothrow_assignable,
        is_trivially_constructible, is_trivially_copy_constructible,
        is_trivially_move_constructible, is_trivially_assignable,
        is_trivially_copy_assignable, is_trivially_move_assignable,
        is_trivially_destructible): Simplify.
    * 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.

[-- Attachment #2: conditional-explicit-default-ctors-pair-tuple5.diff --]
[-- Type: text/plain, Size: 26947 bytes --]

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..7448d5b 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -715,7 +715,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   /// is_unsigned
   template<typename _Tp>
     struct is_unsigned
-    : public __and_<is_arithmetic<_Tp>, __not_<is_signed<_Tp>>>::type
+    : public __and_<is_arithmetic<_Tp>, __not_<is_signed<_Tp>>>
     { };
 
 
@@ -744,7 +744,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<typename _Tp>
     struct __is_array_unknown_bounds
-    : public __and_<is_array<_Tp>, __not_<extent<_Tp>>>::type
+    : public __and_<is_array<_Tp>, __not_<extent<_Tp>>>
     { };
     
   // In N3290 is_destructible does not say anything about function
@@ -862,7 +862,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     struct __is_default_constructible_atom
     : public __and_<__not_<is_void<_Tp>>,
-                    __is_default_constructible_impl<_Tp>>::type
+                    __is_default_constructible_impl<_Tp>>
     { };
 
   template<typename _Tp, bool = is_array<_Tp>::value>
@@ -877,7 +877,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __is_default_constructible_safe<_Tp, true>
     : public __and_<__is_array_known_bounds<_Tp>,
 		    __is_default_constructible_atom<typename
-                      remove_all_extents<_Tp>::type>>::type
+                      remove_all_extents<_Tp>::type>>
     { };
 
   template<typename _Tp>
@@ -957,7 +957,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp, typename _Arg>
     struct __is_direct_constructible_new_safe
     : public __and_<is_destructible<_Tp>,
-                    __is_direct_constructible_impl<_Tp, _Arg>>::type
+                    __is_direct_constructible_impl<_Tp, _Arg>>
     { };
 
   template<typename, typename>
@@ -1029,7 +1029,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     : public __and_<__is_static_castable<_Arg, _Tp>,
                     __not_<__or_<__is_base_to_derived_ref<_Arg, _Tp>,
                                  __is_lvalue_to_rvalue_ref<_Arg, _Tp>
-                   >>>::type
+                   >>>
     { };
 
   template<typename _Tp, typename _Arg>
@@ -1144,7 +1144,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __is_nt_default_constructible_impl<_Tp, true>
     : public __and_<__is_array_known_bounds<_Tp>,
 		    __is_nt_default_constructible_atom<typename
-                      remove_all_extents<_Tp>::type>>::type
+                      remove_all_extents<_Tp>::type>>
     { };
 
   template<typename _Tp>
@@ -1156,7 +1156,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     struct is_nothrow_default_constructible
     : public __and_<is_default_constructible<_Tp>,
-                    __is_nt_default_constructible_impl<_Tp>>::type
+                    __is_nt_default_constructible_impl<_Tp>>
     { };
 
   template<typename _Tp, typename... _Args>
@@ -1179,7 +1179,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp, typename... _Args>
     struct is_nothrow_constructible
     : public __and_<is_constructible<_Tp, _Args...>,
-		    __is_nt_constructible_impl<_Tp, _Args...>>::type
+		    __is_nt_constructible_impl<_Tp, _Args...>>
     { };
 
   template<typename _Tp, bool = __is_referenceable<_Tp>::value>
@@ -1285,7 +1285,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp, typename _Up>
     struct is_nothrow_assignable
     : public __and_<is_assignable<_Tp, _Up>,
-		    __is_nt_assignable_impl<_Tp, _Up>>::type
+		    __is_nt_assignable_impl<_Tp, _Up>>
     { };
 
   template<typename _Tp, bool = __is_referenceable<_Tp>::value>
@@ -1328,7 +1328,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp, typename... _Args>
     struct is_trivially_constructible
     : public __and_<is_constructible<_Tp, _Args...>, integral_constant<bool,
-			__is_trivially_constructible(_Tp, _Args...)>>::type
+			__is_trivially_constructible(_Tp, _Args...)>>
     { };
   
   /// is_trivially_default_constructible
@@ -1337,12 +1337,42 @@ _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 __and_<is_default_constructible<_Tp>,
+                      __is_implicitly_default_constructible_safe<_Tp>>
+  { };
+
   /// is_trivially_copy_constructible
   template<typename _Tp>
     struct is_trivially_copy_constructible
     : public __and_<is_copy_constructible<_Tp>, 
 		    integral_constant<bool,
-			__is_trivially_constructible(_Tp, const _Tp&)>>::type
+			__is_trivially_constructible(_Tp, const _Tp&)>>
     { };
   
   /// is_trivially_move_constructible
@@ -1350,7 +1380,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct is_trivially_move_constructible
     : public __and_<is_move_constructible<_Tp>, 
 		    integral_constant<bool,
-			__is_trivially_constructible(_Tp, _Tp&&)>>::type
+			__is_trivially_constructible(_Tp, _Tp&&)>>
     { };
 
   /// is_trivially_assignable
@@ -1358,7 +1388,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct is_trivially_assignable
     : public __and_<is_assignable<_Tp, _Up>, 
 		    integral_constant<bool,
-			__is_trivially_assignable(_Tp, _Up)>>::type
+			__is_trivially_assignable(_Tp, _Up)>>
     { };
 
   /// is_trivially_copy_assignable
@@ -1366,7 +1396,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct is_trivially_copy_assignable
     : public __and_<is_copy_assignable<_Tp>, 
 		    integral_constant<bool,
-			__is_trivially_assignable(_Tp&, const _Tp&)>>::type
+			__is_trivially_assignable(_Tp&, const _Tp&)>>
     { };
 
   /// is_trivially_move_assignable
@@ -1374,14 +1404,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct is_trivially_move_assignable
     : public __and_<is_move_assignable<_Tp>, 
 		    integral_constant<bool,
-			__is_trivially_assignable(_Tp&, _Tp&&)>>::type
+			__is_trivially_assignable(_Tp&, _Tp&&)>>
     { };
 
   /// is_trivially_destructible
   template<typename _Tp>
     struct is_trivially_destructible
     : public __and_<is_destructible<_Tp>, integral_constant<bool,
-			      __has_trivial_destructor(_Tp)>>::type
+			      __has_trivial_destructor(_Tp)>>
     { };
 
   /// has_trivial_default_constructor (temporary legacy)
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..4e7deda 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 *-*-* } 2239 }
 
 #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..8e5fe53 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 *-*-* } 1904 }
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..4cd0311 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 *-*-* } 1800 }
+// { dg-error "declaration of" "" { target *-*-* } 1757 }
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>{});
 }

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

* Re: [v3 PATCH] Make the default constructors of tuple and pair conditionally explicit.
  2015-11-03  5:02           ` Ville Voutilainen
@ 2015-11-03  8:32             ` Paolo Carlini
  0 siblings, 0 replies; 10+ messages in thread
From: Paolo Carlini @ 2015-11-03  8:32 UTC (permalink / raw)
  To: Ville Voutilainen; +Cc: gcc-patches, libstdc++

Hi,

On 11/03/2015 06:01 AM, Ville Voutilainen wrote:
> On 2 November 2015 at 23:07, Paolo Carlini <paolo.carlini@oracle.com> wrote:
>> Great, thanks a lot. Thinking more about this detail, I wonder if we should
>> therefore apply the below too? Anything I'm missing?
> Tested again on Linux-PPC64. Ok for trunk?
Go ahead!

Paolo.

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

* Re: [v3 PATCH] Make the default constructors of tuple and pair conditionally explicit.
  2015-11-02 21:07         ` Paolo Carlini
  2015-11-03  5:02           ` Ville Voutilainen
@ 2015-11-03 14:43           ` Jonathan Wakely
  2015-11-03 14:49             ` Ville Voutilainen
  1 sibling, 1 reply; 10+ messages in thread
From: Jonathan Wakely @ 2015-11-03 14:43 UTC (permalink / raw)
  To: Paolo Carlini; +Cc: Ville Voutilainen, gcc-patches, libstdc++

On 3 November 2015 at 02:37, Paolo Carlini wrote:
> Hi,
>
> On 11/02/2015 09:20 PM, Ville Voutilainen wrote:
>>
>> On 2 November 2015 at 21:20, Paolo Carlini <paolo.carlini@oracle.com>
>> wrote:
>>>
>>> Can we follow the terse style already used elsewhere (eg,
>>> __is_direct_constructible_new_safe) thus directly inherit from __and_ and
>>> avoid explicit integral_constant? Otherwise patch looks good to me.
>>
>>
>> Sure. Tested again on Linux-PPC64, tests adjusted due to line changes,
>> Changelog entry updated to have a correct date on it.
>
> Great, thanks a lot. Thinking more about this detail, I wonder if we should
> therefore apply the below too? Anything I'm missing?

I have a weak preference for deriving from xxx::type rather than xxx,
so that the traits derive directly from either true_type or
false_type, not indirectly via some other type that derives from
true_type or false_type, but it probably isn't important.

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

* Re: [v3 PATCH] Make the default constructors of tuple and pair conditionally explicit.
  2015-11-03 14:43           ` Jonathan Wakely
@ 2015-11-03 14:49             ` Ville Voutilainen
  0 siblings, 0 replies; 10+ messages in thread
From: Ville Voutilainen @ 2015-11-03 14:49 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: Paolo Carlini, gcc-patches, libstdc++

On 3 November 2015 at 16:42, Jonathan Wakely <jwakely.gcc@gmail.com> wrote:
> On 3 November 2015 at 02:37, Paolo Carlini wrote:
>> Hi,
>>
>> On 11/02/2015 09:20 PM, Ville Voutilainen wrote:
>>>
>>> On 2 November 2015 at 21:20, Paolo Carlini <paolo.carlini@oracle.com>
>>> wrote:
>>>>
>>>> Can we follow the terse style already used elsewhere (eg,
>>>> __is_direct_constructible_new_safe) thus directly inherit from __and_ and
>>>> avoid explicit integral_constant? Otherwise patch looks good to me.
>>>
>>>
>>> Sure. Tested again on Linux-PPC64, tests adjusted due to line changes,
>>> Changelog entry updated to have a correct date on it.
>>
>> Great, thanks a lot. Thinking more about this detail, I wonder if we should
>> therefore apply the below too? Anything I'm missing?
>
> I have a weak preference for deriving from xxx::type rather than xxx,
> so that the traits derive directly from either true_type or
> false_type, not indirectly via some other type that derives from
> true_type or false_type, but it probably isn't important.

I expect the inheritance hierarchies of these things to be linear, so
probably not
a huge matter. I did push the patch already. :)

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

end of thread, other threads:[~2015-11-03 14:49 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-01  3:27 [v3 PATCH] Make the default constructors of tuple and pair conditionally explicit Ville Voutilainen
2015-11-02 15:19 ` Paolo Carlini
2015-11-02 17:00   ` Ville Voutilainen
2015-11-02 19:20     ` Paolo Carlini
2015-11-02 20:20       ` Ville Voutilainen
2015-11-02 21:07         ` Paolo Carlini
2015-11-03  5:02           ` Ville Voutilainen
2015-11-03  8:32             ` Paolo Carlini
2015-11-03 14:43           ` Jonathan Wakely
2015-11-03 14:49             ` Ville Voutilainen

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).