[libcxx] r219785 - Fixes PR21157 'tuple: non-default constructible tuple hard failure' Thanks to Louis Dionne for the bug report and the patch.

Marshall Clow mclow.lists at gmail.com
Wed Oct 15 03:33:04 PDT 2014


Author: marshall
Date: Wed Oct 15 05:33:02 2014
New Revision: 219785

URL: http://llvm.org/viewvc/llvm-project?rev=219785&view=rev
Log:
Fixes PR21157 'tuple: non-default constructible tuple hard failure' Thanks to Louis Dionne for the bug report and the patch.

Modified:
    libcxx/trunk/include/tuple
    libcxx/trunk/test/utilities/tuple/tuple.tuple/tuple.cnstr/UTypes.pass.cpp
    libcxx/trunk/test/utilities/tuple/tuple.tuple/tuple.cnstr/alloc_UTypes.pass.cpp
    libcxx/trunk/test/utilities/tuple/tuple.tuple/tuple.cnstr/default.pass.cpp

Modified: libcxx/trunk/include/tuple
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/tuple?rev=219785&r1=219784&r2=219785&view=diff
==============================================================================
--- libcxx/trunk/include/tuple (original)
+++ libcxx/trunk/include/tuple Wed Oct 15 05:33:02 2014
@@ -376,19 +376,18 @@ template <class ..._Tp>
 _LIBCPP_INLINE_VISIBILITY
 void __swallow(_Tp&&...) _NOEXCEPT {}
 
-template <bool ...> struct __all;
+template <bool ..._B>
+struct __all
+    : is_same<__all<_B...>, __all<(_B, true)...>>
+{ };
 
-template <>
-struct __all<>
-{
-    static const bool value = true;
-};
+template <class _Tp>
+struct __all_default_constructible;
 
-template <bool _B0, bool ... _Bp>
-struct __all<_B0, _Bp...>
-{
-    static const bool value = _B0 && __all<_Bp...>::value;
-};
+template <class ..._Tp>
+struct __all_default_constructible<__tuple_types<_Tp...>>
+    : __all<is_default_constructible<_Tp>::value...>
+{ };
 
 // __tuple_impl
 
@@ -512,6 +511,9 @@ class _LIBCPP_TYPE_VIS_ONLY tuple
         typename tuple_element<_Jp, tuple<_Up...> >::type&& get(tuple<_Up...>&&) _NOEXCEPT;
 public:
 
+    template <bool _Dummy = true, class _Up = typename enable_if<
+        __all<(_Dummy && is_default_constructible<_Tp>::value)...>::value
+    >::type>
     _LIBCPP_INLINE_VISIBILITY
     _LIBCPP_CONSTEXPR tuple()
         _NOEXCEPT_(__all<is_nothrow_default_constructible<_Tp>::value...>::value) {}
@@ -547,6 +549,12 @@ public:
                                      sizeof...(_Up) < sizeof...(_Tp) ?
                                         sizeof...(_Up) :
                                         sizeof...(_Tp)>::type
+                         >::value &&
+                         __all_default_constructible<
+                            typename __make_tuple_types<tuple, sizeof...(_Tp),
+                                sizeof...(_Up) < sizeof...(_Tp) ?
+                                    sizeof...(_Up) :
+                                    sizeof...(_Tp)>::type
                          >::value,
                          bool
                       >::type = false
@@ -587,6 +595,12 @@ public:
                                      sizeof...(_Up) < sizeof...(_Tp) ?
                                         sizeof...(_Up) :
                                         sizeof...(_Tp)>::type
+                         >::value &&
+                         __all_default_constructible<
+                            typename __make_tuple_types<tuple, sizeof...(_Tp),
+                                sizeof...(_Up) < sizeof...(_Tp) ?
+                                    sizeof...(_Up) :
+                                    sizeof...(_Tp)>::type
                          >::value,
                          bool
                       >::type =false
@@ -620,6 +634,12 @@ public:
                                      sizeof...(_Up) < sizeof...(_Tp) ?
                                         sizeof...(_Up) :
                                         sizeof...(_Tp)>::type
+                         >::value &&
+                         __all_default_constructible<
+                            typename __make_tuple_types<tuple, sizeof...(_Tp),
+                                sizeof...(_Up) < sizeof...(_Tp) ?
+                                    sizeof...(_Up) :
+                                    sizeof...(_Tp)>::type
                          >::value
                       >::type
              >

Modified: libcxx/trunk/test/utilities/tuple/tuple.tuple/tuple.cnstr/UTypes.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/utilities/tuple/tuple.tuple/tuple.cnstr/UTypes.pass.cpp?rev=219785&r1=219784&r2=219785&view=diff
==============================================================================
--- libcxx/trunk/test/utilities/tuple/tuple.tuple/tuple.cnstr/UTypes.pass.cpp (original)
+++ libcxx/trunk/test/utilities/tuple/tuple.tuple/tuple.cnstr/UTypes.pass.cpp Wed Oct 15 05:33:02 2014
@@ -16,6 +16,7 @@
 
 #include <tuple>
 #include <cassert>
+#include <type_traits>
 
 #include "../MoveOnly.h"
 
@@ -30,6 +31,8 @@ struct A
 
 #endif
 
+struct NoDefault { NoDefault() = delete; };
+
 int main()
 {
     {
@@ -63,6 +66,14 @@ int main()
         assert(std::get<1>(t) == MoveOnly());
         assert(std::get<2>(t) == MoveOnly());
     }
+    {
+        // Make sure the _Up... constructor SFINAEs out when the types that
+        // are not explicitly initialized are not all default constructible.
+        // Otherwise, std::is_constructible would return true but instantiating
+        // the constructor would fail.
+        static_assert(!std::is_constructible<std::tuple<MoveOnly, NoDefault>, MoveOnly>(), "");
+        static_assert(!std::is_constructible<std::tuple<MoveOnly, MoveOnly, NoDefault>, MoveOnly, MoveOnly>(), "");
+    }
 #if _LIBCPP_STD_VER > 11
     {
         constexpr std::tuple<Empty> t0{Empty()};

Modified: libcxx/trunk/test/utilities/tuple/tuple.tuple/tuple.cnstr/alloc_UTypes.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/utilities/tuple/tuple.tuple/tuple.cnstr/alloc_UTypes.pass.cpp?rev=219785&r1=219784&r2=219785&view=diff
==============================================================================
--- libcxx/trunk/test/utilities/tuple/tuple.tuple/tuple.cnstr/alloc_UTypes.pass.cpp (original)
+++ libcxx/trunk/test/utilities/tuple/tuple.tuple/tuple.cnstr/alloc_UTypes.pass.cpp Wed Oct 15 05:33:02 2014
@@ -22,6 +22,8 @@
 #include "../alloc_first.h"
 #include "../alloc_last.h"
 
+struct NoDefault { NoDefault() = delete; };
+
 int main()
 {
     {
@@ -68,4 +70,19 @@ int main()
         assert(std::get<1>(t) == MoveOnly());
         assert(std::get<2>(t) == MoveOnly());
     }
+    {
+        // Make sure the _Up... constructor SFINAEs out when the types that
+        // are not explicitly initialized are not all default constructible.
+        // Otherwise, std::is_constructible would return true but instantiating
+        // the constructor would fail.
+        static_assert(!std::is_constructible<
+            std::tuple<MoveOnly, NoDefault>,
+            std::allocator_arg_t, A1<int>, MoveOnly
+        >::value, "");
+
+        static_assert(!std::is_constructible<
+            std::tuple<MoveOnly, MoveOnly, NoDefault>,
+            std::allocator_arg_t, A1<int>, MoveOnly, MoveOnly
+        >::value, "");
+    }
 }

Modified: libcxx/trunk/test/utilities/tuple/tuple.tuple/tuple.cnstr/default.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/utilities/tuple/tuple.tuple/tuple.cnstr/default.pass.cpp?rev=219785&r1=219784&r2=219785&view=diff
==============================================================================
--- libcxx/trunk/test/utilities/tuple/tuple.tuple/tuple.cnstr/default.pass.cpp (original)
+++ libcxx/trunk/test/utilities/tuple/tuple.tuple/tuple.cnstr/default.pass.cpp Wed Oct 15 05:33:02 2014
@@ -16,9 +16,23 @@
 #include <tuple>
 #include <string>
 #include <cassert>
+#include <type_traits>
 
 #include "DefaultOnly.h"
 
+struct NoDefault {
+    NoDefault() = delete;
+    explicit NoDefault(int) { }
+};
+
+struct NoExceptDefault {
+    NoExceptDefault() noexcept = default;
+};
+
+struct ThrowingDefault {
+    ThrowingDefault() { }
+};
+
 int main()
 {
     {
@@ -46,6 +60,20 @@ int main()
         assert(std::get<2>(t) == "");
         assert(std::get<3>(t) == DefaultOnly());
     }
+    {
+        // See bug #21157.
+        static_assert(!std::is_default_constructible<std::tuple<NoDefault>>(), "");
+        static_assert(!std::is_default_constructible<std::tuple<DefaultOnly, NoDefault>>(), "");
+        static_assert(!std::is_default_constructible<std::tuple<NoDefault, DefaultOnly, NoDefault>>(), "");
+    }
+    {
+        static_assert(noexcept(std::tuple<NoExceptDefault>()), "");
+        static_assert(noexcept(std::tuple<NoExceptDefault, NoExceptDefault>()), "");
+
+        static_assert(!noexcept(std::tuple<ThrowingDefault, NoExceptDefault>()), "");
+        static_assert(!noexcept(std::tuple<NoExceptDefault, ThrowingDefault>()), "");
+        static_assert(!noexcept(std::tuple<ThrowingDefault, ThrowingDefault>()), "");
+    }
 #ifndef _LIBCPP_HAS_NO_CONSTEXPR
     {
         constexpr std::tuple<> t;





More information about the cfe-commits mailing list