[libc++] Implement LWG 3158

Summary:
LWG 3158 marks the allocator_arg_t constructor of std::tuple as
conditionnally explicit based on whether the default constructors
of the tuple's members are explicitly default constructible.

Reviewers: EricWF, mclow.lists

Subscribers: christof, jkorous, dexonsmith, libcxx-commits

Tags: #libc

Differential Revision: https://reviews.llvm.org/D65232

llvm-svn: 372778
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: e9e1c88ed95040c6dd47c8d818ad08d0286fd00b
diff --git a/include/tuple b/include/tuple
index c33b48a..c4cd3bc 100644
--- a/include/tuple
+++ b/include/tuple
@@ -500,20 +500,22 @@
     struct _CheckArgsConstructor<true, _Dummy>
     {
         template <class ..._Args>
-        static constexpr bool __enable_implicit_default() {
+        struct __enable_implicit_default
             // In C++03, there's no way to implement the resolution of LWG2510.
 #ifdef _LIBCPP_CXX03_LANG
-            return true;
+            : true_type
 #else
-            return __all<__is_implicitly_default_constructible<_Args>::value...>::value;
+            : __all<__is_implicitly_default_constructible<_Args>::value...>
 #endif
-        }
+        { };
 
         template <class ..._Args>
-        static constexpr bool __enable_explicit_default() {
-            return __all<is_default_constructible<_Args>::value...>::value
-                && !__enable_implicit_default<_Args...>();
-        }
+        struct __enable_explicit_default
+            : integral_constant<bool,
+                __all<is_default_constructible<_Args>::value...>::value &&
+                !__enable_implicit_default<_Args...>::value
+            >
+        { };
 
         template <class ..._Args>
         static constexpr bool __enable_explicit() {
@@ -653,14 +655,14 @@
 public:
 
     template <bool _Dummy = true, _EnableIf<
-        _CheckArgsConstructor<_Dummy>::template __enable_implicit_default<_Tp...>()
+        _CheckArgsConstructor<_Dummy>::template __enable_implicit_default<_Tp...>::value
     , void*> = nullptr>
     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
     tuple()
         _NOEXCEPT_(__all<is_nothrow_default_constructible<_Tp>::value...>::value) {}
 
     template <bool _Dummy = true, _EnableIf<
-        _CheckArgsConstructor<_Dummy>::template __enable_explicit_default<_Tp...>()
+        _CheckArgsConstructor<_Dummy>::template __enable_explicit_default<_Tp...>::value
     , void*> = nullptr>
     explicit _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
     tuple()
@@ -669,12 +671,12 @@
     tuple(tuple const&) = default;
     tuple(tuple&&) = default;
 
-    template <class _AllocArgT, class _Alloc, bool _Dummy = true, class = _EnableIf<
+    template <class _AllocArgT, class _Alloc, bool _Dummy = true, _EnableIf<
         _And<
             _IsSame<allocator_arg_t, _AllocArgT>,
-           __dependent_type<is_default_constructible<_Tp>, _Dummy>...
+            typename _CheckArgsConstructor<_Dummy>::template __enable_implicit_default<_Tp...>
        >::value
-      >
+      , void*> = nullptr
     >
     _LIBCPP_INLINE_VISIBILITY
     tuple(_AllocArgT, _Alloc const& __a)
@@ -683,6 +685,20 @@
                     typename __make_tuple_indices<sizeof...(_Tp), 0>::type(),
                     __tuple_types<_Tp...>()) {}
 
+    template <class _AllocArgT, class _Alloc, bool _Dummy = true, _EnableIf<
+        _And<
+            _IsSame<allocator_arg_t, _AllocArgT>,
+            typename _CheckArgsConstructor<_Dummy>::template __enable_explicit_default<_Tp...>
+       >::value
+      , void*> = nullptr
+    >
+    explicit _LIBCPP_INLINE_VISIBILITY
+    tuple(_AllocArgT, _Alloc const& __a)
+      : __base_(allocator_arg_t(), __a,
+                    __tuple_indices<>(), __tuple_types<>(),
+                    typename __make_tuple_indices<sizeof...(_Tp), 0>::type(),
+                    __tuple_types<_Tp...>()) {}
+
     template <bool _Dummy = true,
               typename enable_if
                       <