Implement C++17 tuple bits. Including apply and make_from_tuple.

This patch upgrades <tuple> to be C++17 compliant by implementing:

* tuple_size_v: This was forgotten when implementing the other _v traits.
* std::apply: This was added via LFTS v1 in p0220r1.
* std::make_from_tuple: This was added in p0209r2.

llvm-svn: 275745
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: 03e29a29646843081c403cf036578411502d1b8f
diff --git a/include/tuple b/include/tuple
index b0ab1c9..6805d8c 100644
--- a/include/tuple
+++ b/include/tuple
@@ -76,10 +76,18 @@
 template <class... T> tuple<ATypes...> forward_as_tuple(T&&...) noexcept; // constexpr in C++14
 template <class... T> tuple<T&...> tie(T&...) noexcept; // constexpr in C++14
 template <class... Tuples> tuple<CTypes...> tuple_cat(Tuples&&... tpls); // constexpr in C++14
-  
+
+// [tuple.apply], calling a function with a tuple of arguments:
+template <class F, class Tuple>
+  constexpr decltype(auto) apply(F&& f, Tuple&& t); // C++17
+template <class T, class Tuple>
+  constexpr T make_from_tuple(Tuple&& t); // C++17
+
 // 20.4.1.4, tuple helper classes:
 template <class T> class tuple_size; // undefined
 template <class... T> class tuple_size<tuple<T...>>;
+template <class T>
+ constexpr size_t tuple_size_v = tuple_size<T>::value; // C++17
 template <size_t I, class T> class tuple_element; // undefined
 template <size_t I, class... T> class tuple_element<I, tuple<T...>>;
 template <size_t I, class T>
@@ -1361,6 +1369,50 @@
 
 #endif  // _LIBCPP_HAS_NO_VARIADICS
 
+#if _LIBCPP_STD_VER > 14
+template <class _Tp>
+constexpr size_t tuple_size_v = tuple_size<_Tp>::value;
+
+#define _LIBCPP_NOEXCEPT_RETURN(...) noexcept(noexcept(__VA_ARGS__)) { return __VA_ARGS__; }
+
+template <class _Fn, class _Tuple, size_t ..._Id>
+inline _LIBCPP_INLINE_VISIBILITY
+constexpr decltype(auto) __apply_tuple_impl(_Fn && __f, _Tuple && __t,
+                                            __tuple_indices<_Id...>)
+_LIBCPP_NOEXCEPT_RETURN(
+    _VSTD::__invoke_constexpr(
+        _VSTD::forward<_Fn>(__f),
+        _VSTD::get<_Id>(_VSTD::forward<_Tuple>(__t))...)
+)
+
+template <class _Fn, class _Tuple>
+inline _LIBCPP_INLINE_VISIBILITY
+constexpr decltype(auto) apply(_Fn && __f, _Tuple && __t)
+_LIBCPP_NOEXCEPT_RETURN(
+    _VSTD::__apply_tuple_impl(
+        _VSTD::forward<_Fn>(__f), _VSTD::forward<_Tuple>(__t),
+        typename __make_tuple_indices<tuple_size_v<decay_t<_Tuple>>>::type{})
+)
+
+template <class _Tp, class _Tuple, size_t... _Idx>
+inline _LIBCPP_INLINE_VISIBILITY
+constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, __tuple_indices<_Idx...>)
+_LIBCPP_NOEXCEPT_RETURN(
+    _Tp(_VSTD::get<_Idx>(_VSTD::forward<_Tuple>(__t))...)
+)
+
+template <class _Tp, class _Tuple>
+inline _LIBCPP_INLINE_VISIBILITY
+constexpr _Tp make_from_tuple(_Tuple&& __t)
+_LIBCPP_NOEXCEPT_RETURN(
+    _VSTD::__make_from_tuple_impl<_Tp>(_VSTD::forward<_Tuple>(__t),
+        typename __make_tuple_indices<tuple_size_v<decay_t<_Tuple>>>::type{})
+)
+
+#undef _LIBCPP_NOEXCEPT_RETURN
+
+#endif // _LIBCPP_STD_VER > 14
+
 _LIBCPP_END_NAMESPACE_STD
 
 #endif  // _LIBCPP_TUPLE