[libc++] Take 2: Implement LWG 2510

Summary:
LWG2510 makes tag types like allocator_arg_t explicitly default
constructible instead of implicitly default constructible. It also
makes the constructors for std::pair and std::tuple conditionally
explicit based on the explicit-ness of the default constructibility
for the pair/tuple's elements.

This was previously committed as r372777 and reverted in r372832 due to
the commit breaking LLVM's build in C++14 mode. This issue has now been
addressed.

Reviewers: mclow.lists

Subscribers: christof, jkorous, dexonsmith, libcxx-commits

Tags: #libc

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

llvm-svn: 372983
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: e16f2cb6789286dbfa4a184cef25b91dfb499206
diff --git a/include/tuple b/include/tuple
index 32bc869..c33b48a 100644
--- a/include/tuple
+++ b/include/tuple
@@ -19,7 +19,7 @@
 template <class... T>
 class tuple {
 public:
-    constexpr tuple();
+    explicit(see-below) constexpr tuple();
     explicit(see-below) tuple(const T&...);  // constexpr in C++14
     template <class... U>
         explicit(see-below) tuple(U&&...);  // constexpr in C++14
@@ -500,8 +500,19 @@
     struct _CheckArgsConstructor<true, _Dummy>
     {
         template <class ..._Args>
-        static constexpr bool __enable_default() {
-            return __all<is_default_constructible<_Args>::value...>::value;
+        static constexpr bool __enable_implicit_default() {
+            // In C++03, there's no way to implement the resolution of LWG2510.
+#ifdef _LIBCPP_CXX03_LANG
+            return true;
+#else
+            return __all<__is_implicitly_default_constructible<_Args>::value...>::value;
+#endif
+        }
+
+        template <class ..._Args>
+        static constexpr bool __enable_explicit_default() {
+            return __all<is_default_constructible<_Args>::value...>::value
+                && !__enable_implicit_default<_Args...>();
         }
 
         template <class ..._Args>
@@ -641,11 +652,18 @@
         const typename tuple_element<_Jp, tuple<_Up...> >::type&& get(const tuple<_Up...>&&) _NOEXCEPT;
 public:
 
-    template <bool _Dummy = true, class = typename enable_if<
-        _CheckArgsConstructor<_Dummy>::template __enable_default<_Tp...>()
-    >::type>
-    _LIBCPP_INLINE_VISIBILITY
-    _LIBCPP_CONSTEXPR tuple()
+    template <bool _Dummy = true, _EnableIf<
+        _CheckArgsConstructor<_Dummy>::template __enable_implicit_default<_Tp...>()
+    , 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...>()
+    , void*> = nullptr>
+    explicit _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
+    tuple()
         _NOEXCEPT_(__all<is_nothrow_default_constructible<_Tp>::value...>::value) {}
 
     tuple(tuple const&) = default;