[libcxx-commits] [libcxx] [libc++] Add __simple_tuple and replace a bunch of uses of tuple with it (PR #214566)
via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Aug 17 05:12:53 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Nikolas Klauser (philnik777)
<details>
<summary>Changes</summary>
`__simply_tuple` is significantly lighter than `tuple`, making it significantly faster to compile. For example, it is 6x faster to compile `std::views::transform(std::identity())` with this. `<mutex>` also becomes ~30% faster to compile.
---
Patch is 36.64 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/214566.diff
27 Files Affected:
- (modified) libcxx/include/CMakeLists.txt (+2-1)
- (modified) libcxx/include/__functional/bind_back.h (+19-26)
- (modified) libcxx/include/__functional/bind_front.h (+9-9)
- (modified) libcxx/include/__functional/perfect_forward.h (+18-15)
- (modified) libcxx/include/__mutex/once_flag.h (+5-10)
- (added) libcxx/include/__tuple/simple_tuple.h (+108)
- (modified) libcxx/include/algorithm (+2)
- (modified) libcxx/include/future (+7-5)
- (modified) libcxx/include/module.modulemap.in (+2-1)
- (modified) libcxx/include/mutex (+8-12)
- (modified) libcxx/include/numeric (+2)
- (modified) libcxx/include/tuple (+2-2)
- (modified) libcxx/include/vector (+4)
- (modified) libcxx/test/libcxx/transitive_includes/cxx26.csv (-6)
- (modified) libcxx/test/std/thread/futures/futures.async/async.verify.cpp (+2-4)
- (modified) libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/assign.compile.pass.cpp (+1)
- (modified) libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/copy.compile.pass.cpp (+1)
- (modified) libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_assign.compile.pass.cpp (+1)
- (modified) libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_ctor.compile.pass.cpp (+1)
- (modified) libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.mod/member_swap.pass.cpp (+1)
- (modified) libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.mod/nonmember_swap.pass.cpp (+1)
- (modified) libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.mod/release.pass.cpp (+1)
- (modified) libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.obs/mutex.pass.cpp (+1)
- (modified) libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.obs/op_bool.pass.cpp (+1)
- (modified) libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.obs/owns_lock.pass.cpp (+1)
- (modified) libcxx/test/std/utilities/function.objects/func.bind.partial/bind_back.verify.cpp (+2-2)
- (modified) libcxx/test/std/utilities/function.objects/func.bind.partial/bind_front.nttp.verify.cpp (+1-1)
``````````diff
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index d24ae7a73a825..21276786837c3 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -619,7 +619,7 @@ set(files
__memory/noexcept_move_assign_container.h
__memory/out_ptr.h
__memory/pointer_traits.h
- __memory/pstl.h
+ __memory/pstl.h
__memory/ranges_construct_at.h
__memory/ranges_destroy.h
__memory/ranges_uninitialized_algorithms.h
@@ -830,6 +830,7 @@ set(files
__tuple/find_index.h
__tuple/ignore.h
__tuple/sfinae_helpers.h
+ __tuple/simple_tuple.h
__tuple/tuple_element.h
__tuple/tuple_like.h
__tuple/tuple_like_no_subrange.h
diff --git a/libcxx/include/__functional/bind_back.h b/libcxx/include/__functional/bind_back.h
index 41177144d81fe..575d7813f7d59 100644
--- a/libcxx/include/__functional/bind_back.h
+++ b/libcxx/include/__functional/bind_back.h
@@ -13,10 +13,10 @@
#include <__config>
#include <__functional/invoke.h>
#include <__functional/perfect_forward.h>
+#include <__tuple/simple_tuple.h>
#include <__type_traits/decay.h>
#include <__utility/forward.h>
#include <__utility/integer_sequence.h>
-#include <tuple>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -26,40 +26,33 @@ _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 20
-template <size_t _NBound, class = make_index_sequence<_NBound>>
-struct __bind_back_op;
-
-template <size_t _NBound, size_t... _Ip>
-struct __bind_back_op<_NBound, index_sequence<_Ip...>> {
+struct __bind_back_op {
template <class _Fn, class _BoundArgs, class... _Args>
_LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Fn&& __f, _BoundArgs&& __bound_args, _Args&&... __args) const
- noexcept(noexcept(std::invoke(std::forward<_Fn>(__f),
- std::forward<_Args>(__args)...,
- std::get<_Ip>(std::forward<_BoundArgs>(__bound_args))...)))
- -> decltype(std::invoke(std::forward<_Fn>(__f),
- std::forward<_Args>(__args)...,
- std::get<_Ip>(std::forward<_BoundArgs>(__bound_args))...)) {
- return std::invoke(std::forward<_Fn>(__f),
- std::forward<_Args>(__args)...,
- std::get<_Ip>(std::forward<_BoundArgs>(__bound_args))...);
+ noexcept(noexcept(decay_t<_BoundArgs>::__apply_back(
+ std::forward<_BoundArgs>(__bound_args), std::forward<_Fn>(__f), std::forward<_Args>(__args)...)))
+ -> decltype(decay_t<_BoundArgs>::__apply_back(
+ std::forward<_BoundArgs>(__bound_args), std::forward<_Fn>(__f), std::forward<_Args>(__args)...)) {
+ return decay_t<_BoundArgs>::__apply_back(
+ std::forward<_BoundArgs>(__bound_args), std::forward<_Fn>(__f), std::forward<_Args>(__args)...);
}
};
template <class _Fn, class _BoundArgs>
-struct __bind_back_t : __perfect_forward<__bind_back_op<tuple_size_v<_BoundArgs>>, _Fn, _BoundArgs> {
- using __perfect_forward<__bind_back_op<tuple_size_v<_BoundArgs>>, _Fn, _BoundArgs>::__perfect_forward;
+struct __bind_back_t : __perfect_forward<__bind_back_op, _Fn, _BoundArgs> {
+ using __perfect_forward<__bind_back_op, _Fn, _BoundArgs>::__perfect_forward;
};
template <class _Fn, class... _Args>
requires is_constructible_v<decay_t<_Fn>, _Fn> && is_move_constructible_v<decay_t<_Fn>> &&
- (is_constructible_v<decay_t<_Args>, _Args> && ...) && (is_move_constructible_v<decay_t<_Args>> && ...)
+ (is_constructible_v<decay_t<_Args>, _Args> && ...) && (is_move_constructible_v<decay_t<_Args>> && ...)
_LIBCPP_HIDE_FROM_ABI constexpr auto __bind_back(_Fn&& __f, _Args&&... __args) noexcept(
- noexcept(__bind_back_t<decay_t<_Fn>, tuple<decay_t<_Args>...>>(
- std::forward<_Fn>(__f), std::forward_as_tuple(std::forward<_Args>(__args)...))))
- -> decltype(__bind_back_t<decay_t<_Fn>, tuple<decay_t<_Args>...>>(
- std::forward<_Fn>(__f), std::forward_as_tuple(std::forward<_Args>(__args)...))) {
- return __bind_back_t<decay_t<_Fn>, tuple<decay_t<_Args>...>>(
- std::forward<_Fn>(__f), std::forward_as_tuple(std::forward<_Args>(__args)...));
+ noexcept(__bind_back_t<decay_t<_Fn>, __simple_tuple<decay_t<_Args>...>>(
+ std::forward<_Fn>(__f), __simple_tuple<decay_t<_Args>...>(std::forward<_Args>(__args)...))))
+ -> decltype(__bind_back_t<decay_t<_Fn>, __simple_tuple<decay_t<_Args>...>>(
+ std::forward<_Fn>(__f), __simple_tuple<decay_t<_Args>...>(std::forward<_Args>(__args)...))) {
+ return __bind_back_t<decay_t<_Fn>, __simple_tuple<decay_t<_Args>...>>(
+ std::forward<_Fn>(__f), __simple_tuple<decay_t<_Args>...>(std::forward<_Args>(__args)...));
}
# if _LIBCPP_STD_VER >= 23
@@ -71,8 +64,8 @@ template <class _Fn, class... _Args>
"bind_back requires all decay_t<Args> to be constructible from respective Args");
static_assert((is_move_constructible_v<decay_t<_Args>> && ...),
"bind_back requires all decay_t<Args> to be move constructible");
- return __bind_back_t<decay_t<_Fn>, tuple<decay_t<_Args>...>>(
- std::forward<_Fn>(__f), std::forward_as_tuple(std::forward<_Args>(__args)...));
+ return __bind_back_t<decay_t<_Fn>, __simple_tuple<decay_t<_Args>...>>(
+ std::forward<_Fn>(__f), __simple_tuple<decay_t<_Args>...>(std::forward<_Args>(__args)...));
}
# endif // _LIBCPP_STD_VER >= 23
diff --git a/libcxx/include/__functional/bind_front.h b/libcxx/include/__functional/bind_front.h
index 97f8f4c458702..de354bbdb0f4a 100644
--- a/libcxx/include/__functional/bind_front.h
+++ b/libcxx/include/__functional/bind_front.h
@@ -31,8 +31,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD
struct __bind_front_op {
template <class... _Args>
- _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) const noexcept(
- noexcept(std::invoke(std::forward<_Args>(__args)...))) -> decltype(std::invoke(std::forward<_Args>(__args)...)) {
+ _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) const
+ noexcept(noexcept(std::invoke(std::forward<_Args>(__args)...)))
+ -> decltype(std::invoke(std::forward<_Args>(__args)...)) {
return std::invoke(std::forward<_Args>(__args)...);
}
};
@@ -58,15 +59,14 @@ struct __nttp_bind_front_t;
template <auto _Fn, size_t... _Indices, class... _BoundArgs>
struct __nttp_bind_front_t<_Fn, index_sequence<_Indices...>, _BoundArgs...> {
- tuple<_BoundArgs...> __bound_args_;
+ using _TupleT _LIBCPP_NODEBUG = __simple_tuple<_BoundArgs...>;
+ _TupleT __bound_args_;
template <class _Self, class... _Args>
- _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(this _Self&& __self, _Args&&... __args) noexcept(noexcept(std::invoke(
- _Fn, std::get<_Indices>(std::forward<_Self>(__self).__bound_args_)..., std::forward<_Args>(__args)...)))
- -> decltype(std::invoke(
- _Fn, std::get<_Indices>(std::forward<_Self>(__self).__bound_args_)..., std::forward<_Args>(__args)...)) {
- return std::invoke(
- _Fn, std::get<_Indices>(std::forward<_Self>(__self).__bound_args_)..., std::forward<_Args>(__args)...);
+ _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(this _Self&& __self, _Args&&... __args) noexcept(
+ noexcept(_TupleT::__apply(std::forward<_Self>(__self).__bound_args_, _Fn, std::forward<_Args>(__args)...)))
+ -> decltype(_TupleT::__apply(std::forward<_Self>(__self).__bound_args_, _Fn, std::forward<_Args>(__args)...)) {
+ return _TupleT::__apply(std::forward<_Self>(__self).__bound_args_, _Fn, std::forward<_Args>(__args)...);
}
};
diff --git a/libcxx/include/__functional/perfect_forward.h b/libcxx/include/__functional/perfect_forward.h
index c0408b410e2f9..83ef1c3ba1331 100644
--- a/libcxx/include/__functional/perfect_forward.h
+++ b/libcxx/include/__functional/perfect_forward.h
@@ -12,6 +12,8 @@
#include <__config>
#include <__cstddef/size_t.h>
+#include <__tuple/simple_tuple.h>
+#include <__type_traits/conjunction.h>
#include <__type_traits/enable_if.h>
#include <__type_traits/invoke.h>
#include <__type_traits/is_constructible.h>
@@ -19,7 +21,6 @@
#include <__utility/forward.h>
#include <__utility/integer_sequence.h>
#include <__utility/move.h>
-#include <tuple>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -38,10 +39,12 @@ struct __perfect_forward_impl;
template <class _Op, size_t... _Idx, class... _BoundArgs>
struct __perfect_forward_impl<_Op, index_sequence<_Idx...>, _BoundArgs...> {
private:
- tuple<_BoundArgs...> __bound_args_;
+ using _TupleT _LIBCPP_NODEBUG = __simple_tuple<_BoundArgs...>;
+
+ _TupleT __bound_args_;
public:
- template <class... _Args, class = enable_if_t< is_constructible_v<tuple<_BoundArgs...>, _Args&&...> >>
+ template <class... _Args, enable_if_t<_And<is_constructible<_BoundArgs, _Args&&>...>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI explicit constexpr __perfect_forward_impl(_Args&&... __bound_args)
: __bound_args_(std::forward<_Args>(__bound_args)...) {}
@@ -53,9 +56,9 @@ struct __perfect_forward_impl<_Op, index_sequence<_Idx...>, _BoundArgs...> {
template <class... _Args, class = enable_if_t<is_invocable_v<_Op, _BoundArgs&..., _Args...>>>
_LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) & noexcept(
- noexcept(_Op()(std::get<_Idx>(__bound_args_)..., std::forward<_Args>(__args)...)))
- -> decltype(_Op()(std::get<_Idx>(__bound_args_)..., std::forward<_Args>(__args)...)) {
- return _Op()(std::get<_Idx>(__bound_args_)..., std::forward<_Args>(__args)...);
+ noexcept(_TupleT::__apply(__bound_args_, _Op(), std::forward<_Args>(__args)...)))
+ -> decltype(_TupleT::__apply(__bound_args_, _Op(), std::forward<_Args>(__args)...)) {
+ return _TupleT::__apply(__bound_args_, _Op(), std::forward<_Args>(__args)...);
}
template <class... _Args, class = enable_if_t<!is_invocable_v<_Op, _BoundArgs&..., _Args...>>>
@@ -63,9 +66,9 @@ struct __perfect_forward_impl<_Op, index_sequence<_Idx...>, _BoundArgs...> {
template <class... _Args, class = enable_if_t<is_invocable_v<_Op, _BoundArgs const&..., _Args...>>>
_LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) const& noexcept(
- noexcept(_Op()(std::get<_Idx>(__bound_args_)..., std::forward<_Args>(__args)...)))
- -> decltype(_Op()(std::get<_Idx>(__bound_args_)..., std::forward<_Args>(__args)...)) {
- return _Op()(std::get<_Idx>(__bound_args_)..., std::forward<_Args>(__args)...);
+ noexcept(_TupleT::__apply(__bound_args_, _Op(), std::forward<_Args>(__args)...)))
+ -> decltype(_TupleT::__apply(__bound_args_, _Op(), std::forward<_Args>(__args)...)) {
+ return _TupleT::__apply(__bound_args_, _Op(), std::forward<_Args>(__args)...);
}
template <class... _Args, class = enable_if_t<!is_invocable_v<_Op, _BoundArgs const&..., _Args...>>>
@@ -73,9 +76,9 @@ struct __perfect_forward_impl<_Op, index_sequence<_Idx...>, _BoundArgs...> {
template <class... _Args, class = enable_if_t<is_invocable_v<_Op, _BoundArgs..., _Args...>>>
_LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) && noexcept(
- noexcept(_Op()(std::get<_Idx>(std::move(__bound_args_))..., std::forward<_Args>(__args)...)))
- -> decltype(_Op()(std::get<_Idx>(std::move(__bound_args_))..., std::forward<_Args>(__args)...)) {
- return _Op()(std::get<_Idx>(std::move(__bound_args_))..., std::forward<_Args>(__args)...);
+ noexcept(_TupleT::__apply(std::move(__bound_args_), _Op(), std::forward<_Args>(__args)...)))
+ -> decltype(_TupleT::__apply(std::move(__bound_args_), _Op(), std::forward<_Args>(__args)...)) {
+ return _TupleT::__apply(std::move(__bound_args_), _Op(), std::forward<_Args>(__args)...);
}
template <class... _Args, class = enable_if_t<!is_invocable_v<_Op, _BoundArgs..., _Args...>>>
@@ -83,9 +86,9 @@ struct __perfect_forward_impl<_Op, index_sequence<_Idx...>, _BoundArgs...> {
template <class... _Args, class = enable_if_t<is_invocable_v<_Op, _BoundArgs const..., _Args...>>>
_LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) const&& noexcept(
- noexcept(_Op()(std::get<_Idx>(std::move(__bound_args_))..., std::forward<_Args>(__args)...)))
- -> decltype(_Op()(std::get<_Idx>(std::move(__bound_args_))..., std::forward<_Args>(__args)...)) {
- return _Op()(std::get<_Idx>(std::move(__bound_args_))..., std::forward<_Args>(__args)...);
+ noexcept(_TupleT::__apply(std::move(__bound_args_), _Op(), std::forward<_Args>(__args)...)))
+ -> decltype(_TupleT::__apply(std::move(__bound_args_), _Op(), std::forward<_Args>(__args)...)) {
+ return _TupleT::__apply(std::move(__bound_args_), _Op(), std::forward<_Args>(__args)...);
}
template <class... _Args, class = enable_if_t<!is_invocable_v<_Op, _BoundArgs const..., _Args...>>>
diff --git a/libcxx/include/__mutex/once_flag.h b/libcxx/include/__mutex/once_flag.h
index 9999852b8b78a..f5cc8bed2d19a 100644
--- a/libcxx/include/__mutex/once_flag.h
+++ b/libcxx/include/__mutex/once_flag.h
@@ -11,15 +11,10 @@
#include <__config>
#include <__memory/addressof.h>
-#include <__tuple/tuple_size.h>
+#include <__tuple/simple_tuple.h>
#include <__type_traits/invoke.h>
#include <__utility/forward.h>
-#include <__utility/integer_sequence.h>
#include <__utility/move.h>
-#include <cstdint>
-#ifndef _LIBCPP_CXX03_LANG
-# include <tuple>
-#endif
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -87,9 +82,9 @@ class __call_once_param {
_LIBCPP_HIDE_FROM_ABI explicit __call_once_param(_Fp& __f) : __f_(__f) {}
_LIBCPP_HIDE_FROM_ABI void operator()() {
- [&]<size_t... _Indices>(__index_sequence<_Indices...>) -> void {
- std::__invoke(std::get<_Indices>(std::move(__f_))...);
- }(__make_index_sequence<tuple_size<_Fp>::value>());
+ _Fp::__apply(std::move(__f_), []<class... _Args>(_Args&&... __args) -> void {
+ std::__invoke(std::forward<_Args>(__args)...);
+ });
}
};
@@ -131,7 +126,7 @@ inline _LIBCPP_HIDE_FROM_ABI _ValueType __libcpp_acquire_load(_ValueType const*
template <class _Callable, class... _Args>
inline _LIBCPP_HIDE_FROM_ABI void call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args) {
if (__libcpp_acquire_load(&__flag.__state_) != once_flag::_Complete) {
- typedef tuple<_Callable&&, _Args&&...> _Gp;
+ typedef __simple_tuple<_Callable&&, _Args&&...> _Gp;
_Gp __f(std::forward<_Callable>(__func), std::forward<_Args>(__args)...);
__call_once_param<_Gp> __p(__f);
std::__call_once(__flag.__state_, std::addressof(__p), std::addressof(__call_once_proxy<_Gp>));
diff --git a/libcxx/include/__tuple/simple_tuple.h b/libcxx/include/__tuple/simple_tuple.h
new file mode 100644
index 0000000000000..71da2f19679a6
--- /dev/null
+++ b/libcxx/include/__tuple/simple_tuple.h
@@ -0,0 +1,108 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___TUPLE_SIMPLE_TUPLE_H
+#define _LIBCPP___TUPLE_SIMPLE_TUPLE_H
+
+#include <__config>
+#include <__cstddef/size_t.h>
+#include <__type_traits/conditional.h>
+#include <__type_traits/copy_cvref.h>
+#include <__type_traits/disjunction.h>
+#include <__type_traits/enable_if.h>
+#include <__type_traits/integral_constant.h>
+#include <__type_traits/invoke.h>
+#include <__type_traits/is_empty.h>
+#include <__type_traits/is_final.h>
+#include <__type_traits/is_reference.h>
+#include <__type_traits/is_same.h>
+#include <__type_traits/remove_cvref.h>
+#include <__utility/forward.h>
+#include <__utility/integer_sequence.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+#ifndef _LIBCPP_CXX03_LANG
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template <size_t, class _Tp, bool = is_empty<_Tp>::value && !__is_final_v<_Tp>>
+struct __simple_tuple_base {
+ _Tp __val_;
+
+ __simple_tuple_base() = default;
+
+ template <class _Arg, __enable_if_t<_IsNotSame<__remove_cvref_t<_Arg>, __simple_tuple_base>::value, int> = 0>
+ constexpr __simple_tuple_base(_Arg&& __arg) : __val_(std::forward<_Arg>(__arg)) {}
+};
+
+template <size_t _Index, class _Tp>
+struct __simple_tuple_base<_Index, _Tp, true> {
+ _LIBCPP_NO_UNIQUE_ADDRESS _Tp __val_;
+
+ __simple_tuple_base() = default;
+
+ template <class _Arg, __enable_if_t<_IsNotSame<__remove_cvref_t<_Arg>, __simple_tuple_base>::value, int> = 0>
+ constexpr __simple_tuple_base(_Arg&& __arg) : __val_(std::forward<_Arg>(__arg)) {}
+};
+
+template <class _IndexSequence, class... _Bases>
+struct __simple_tuple_impl;
+
+template <class _Ap, class _Bp>
+using __tuple_forward _LIBCPP_NODEBUG = _If<is_reference<_Bp>::value, _Bp, __copy_cvref_t<_Ap, _Bp>>;
+
+template <size_t... _Indices, class... _Types>
+struct __simple_tuple_impl<__index_sequence<_Indices...>, _Types...> : __simple_tuple_base<_Indices, _Types>... {
+ __simple_tuple_impl() = default;
+
+ template <class... _Args,
+ __enable_if_t<_Or<integral_constant<bool, (sizeof...(_Args) != 1)>,
+ _IsNotSame<__remove_cvref_t<_Args>, __simple_tuple_impl>...>::value,
+ int> = 0>
+ constexpr __simple_tuple_impl(_Args&&... __args)
+ : __simple_tuple_base<_Indices, _Types>(std::forward<_Args>(__args))... {}
+
+ template <class _Self, class _Func, class... _Args>
+ static constexpr auto __apply(_Self&& __self, _Func&& __func, _Args&&... __args) noexcept(
+ __is_nothrow_invocable_v<_Func, __tuple_forward<_Self, _Types>..., _Args...>)
+ -> __invoke_result_t<_Func, __tuple_forward<_Self, _Types>..., _Args...> {
+ return std::__invoke(
+ std::forward<_Func>(__func),
+ static_cast<__tuple_forward<_Self, _Types>&&>(
+ static_cast<__copy_cvref_t<_Self, __simple_tuple_base<_Indices, _Types>>&&>(__self).__val_)...,
+ std::forward<_Args>(__args)...);
+ }
+
+ template <class _Self, class _Func, class... _Args>
+ static constexpr auto __apply_back(_Self&& __self, _Func&& __func, _Args&&... __args) noexcept(
+ __is_nothrow_invocable_v<_Func, _Args..., __tuple_forward<_Self, _Types>...>)
+ -> __invoke_result_t<_Func, _Args..., __tuple_forward<_Self, _Types>...> {
+ return std::__invoke(
+ std::forward<_Func>(__func),
+ std::forward<_Args>(__args)...,
+ static_cast<__tuple_forward<_Self, _Types>&&>(
+ static_cast<__copy_cvref_t<_Self, __simple_tuple_base<_Indices, _Types>>&&>(__self).__val_)...);
+ }
+};
+
+template <class... _Args>
+using __simple_tuple _LIBCPP_NODEBUG = __simple_tuple_impl<__index_sequence_for<_Args...>, _Args...>;
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_CXX03_LANG
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___TUPLE_SIMPLE_TUPLE_H
diff --git a/libcxx/include/algorithm b/libcxx/include/algorithm
index 1e1587cc56131..63eae0aa37b4a 100644
--- a/libcxx/include/algorithm
+++ b/libcxx/include/algorithm
@@ -2106,7 +2106,9 @@ template <class BidirectionalIterator, class Compare>
# if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER >= 17 && _LIBCPP_STD_VER <= 23
# include <optional>
+# include <tuple>
# endif
+
#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
#endif // _LIBCPP_ALGORITHM
diff --git a/libcxx/include/future b/libcxx/include/future
index 30091660a4286..fa331887299df 100644
--- a/libcxx/include/future
+++ b/libcxx/include/future
@@ -390,9 +390,11 @@ template <class R, class Alloc> struct uses_allocator<packaged_task<R>, Alloc>;
# include <__system_error/error_code.h>
# include <__system_error/error_condition.h>
# include <__thread/thread.h>
+# include <__tuple/simple_tuple.h>
# include <__type_traits/add_reference.h>
# include <__type_traits/aligned_storage.h>
# include <__type_traits/conditional.h>
+# include <__type_traits/conjunction.h>
# include <__type_traits/decay.h>
# include <__type_traits/enable_if.h>
# include <__type_traits/invoke.h>
@@ -408,7 +410,6 @@ template <class R, class Alloc> struct uses_allocator<packag...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/214566
More information about the libcxx-commits
mailing list