diff options
author | Patrick Palka <ppalka@redhat.com> | 2022-08-23 13:42:37 -0400 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2022-08-23 13:42:37 -0400 |
commit | 72886fcc6269531bbf3d9a09b3d64644963bff0d (patch) | |
tree | ad19ae595e927e200e464a4499b997c8e0d33660 /libstdc++-v3/include/std/tuple | |
parent | 02f6b405f0e9dc7a8868fecef9a048b79c433125 (diff) | |
download | gcc-72886fcc6269531bbf3d9a09b3d64644963bff0d.zip gcc-72886fcc6269531bbf3d9a09b3d64644963bff0d.tar.gz gcc-72886fcc6269531bbf3d9a09b3d64644963bff0d.tar.bz2 |
libstdc++: Implement std::pair/tuple/misc enhancements from P2321R2
This implements the non-<ranges> changes from P2321R2, which primarily
consist of additional converting constructors, assignment operator and
swap overloads for std::pair and std::tuple.
libstdc++-v3/ChangeLog:
* include/bits/stl_bvector.h (_Bit_reference::operator=): Define
const overload for C++23 as per P2321R2.
* include/bits/stl_pair.h (pair::swap): Likewise.
(pair::pair): Define additional converting constructors for
C++23 as per P2321R2.
(pair::operator=): Define const overloads for C++23 as per
P2321R2.
(swap): Define overload taking const pair& for C++23 as per
P2321R2.
(basic_common_reference): Define partial specialization for
pair for C++23 as per P2321R2.
(common_type): Likewise.
* include/bits/uses_allocator_args.h
(uses_allocator_construction_args): Define additional pair
overloads for C++23 as per P2321R2.
* include/std/tuple (_Tuple_impl::_Tuple_impl): Define
additional converting constructors for C++23 as per P2321R2.
(_Tuple_impl::_M_assign): Define const overloads for C++23
as per P2321R2.
(_Tuple_impl::_M_swap): Likewise.
(tuple::__constructible): Define as a convenient renaming of
_TCC<true>::__constructible.
(tuple::__convertible): As above but for _TCC<true>::__convertible.
(tuple::tuple): Define additional converting constructors for
C++23 as per P2321R2.
(tuple::operator=): Define const overloads for C++23 as per
P2321R2.
(tuple::swap): Likewise.
(basic_common_reference): Define partial specialization for
tuple for C++23 as per P2321R2.
(common_type): Likewise.
* testsuite/20_util/pair/p2321r2.cc: New test.
* testsuite/20_util/tuple/p2321r2.cc: New test.
* testsuite/23_containers/vector/bool/element_access/1.cc: New test.
Diffstat (limited to 'libstdc++-v3/include/std/tuple')
-rw-r--r-- | libstdc++-v3/include/std/tuple | 416 |
1 files changed, 416 insertions, 0 deletions
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 7f9c072..05433d5 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -316,6 +316,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) { } +#if __cplusplus > 202002L + template<typename... _UElements> + constexpr + _Tuple_impl(_Tuple_impl<_Idx, _UElements...>& __in) + : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)), + _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in)) + { } + + template<typename _UHead, typename... _UTails> + constexpr + _Tuple_impl(const _Tuple_impl<_Idx, _UHead, _UTails...>&& __in) + : _Inherited(std::move + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))), + _Base(std::forward<const _UHead> + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) + { } +#endif // C++23 + template<typename _Alloc> _GLIBCXX20_CONSTEXPR _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a) @@ -379,6 +397,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) { } +#if __cplusplus > 202002L + template<typename _Alloc, typename _UHead, typename... _UTails> + constexpr + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + _Tuple_impl<_Idx, _UHead, _UTails...>& __in) + : _Inherited(__tag, __a, + _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)), + _Base(__use_alloc<_Head, _Alloc, _UHead&>(__a), + _Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)) + { } + + template<typename _Alloc, typename _UHead, typename... _UTails> + constexpr + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + const _Tuple_impl<_Idx, _UHead, _UTails...>&& __in) + : _Inherited(__tag, __a, std::move + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))), + _Base(__use_alloc<_Head, _Alloc, const _UHead>(__a), + std::forward<const _UHead> + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) + { } +#endif // C++23 + template<typename... _UElements> _GLIBCXX20_CONSTEXPR void @@ -400,6 +441,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))); } +#if __cplusplus > 202002L + template<typename... _UElements> + constexpr void + _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in) const + { + _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in); + _M_tail(*this)._M_assign( + _Tuple_impl<_Idx, _UElements...>::_M_tail(__in)); + } + + template<typename _UHead, typename... _UTails> + constexpr void + _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) const + { + _M_head(*this) = std::forward<_UHead> + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)); + _M_tail(*this)._M_assign( + std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))); + } +#endif // C++23 + protected: _GLIBCXX20_CONSTEXPR void @@ -409,6 +471,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION swap(_M_head(*this), _M_head(__in)); _Inherited::_M_swap(_M_tail(__in)); } + +#if __cplusplus > 202002L + constexpr void + _M_swap(const _Tuple_impl& __in) const + { + using std::swap; + swap(_M_head(*this), _M_head(__in)); + _Inherited::_M_swap(_M_tail(__in)); + } +#endif // C++23 }; // Basis case of inheritance recursion. @@ -469,6 +541,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _Base(std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in))) { } +#if __cplusplus > 202002L + template<typename _UHead> + constexpr + _Tuple_impl(_Tuple_impl<_Idx, _UHead>& __in) + : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in)) + { } + + template<typename _UHead> + constexpr + _Tuple_impl(const _Tuple_impl<_Idx, _UHead>&& __in) + : _Base(std::forward<const _UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in))) + { } +#endif // C++23 + template<typename _Alloc> _GLIBCXX20_CONSTEXPR _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a) @@ -521,6 +607,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in))) { } +#if __cplusplus > 202002L + template<typename _Alloc, typename _UHead> + constexpr + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + _Tuple_impl<_Idx, _UHead>& __in) + : _Base(__use_alloc<_Head, _Alloc, _UHead&>(__a), + _Tuple_impl<_Idx, _UHead>::_M_head(__in)) + { } + + template<typename _Alloc, typename _UHead> + constexpr + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + const _Tuple_impl<_Idx, _UHead>&& __in) + : _Base(__use_alloc<_Head, _Alloc, const _UHead>(__a), + std::forward<const _UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in))) + { } +#endif // C++23 + template<typename _UHead> _GLIBCXX20_CONSTEXPR void @@ -538,6 +642,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)); } +#if __cplusplus > 202002L + template<typename _UHead> + constexpr void + _M_assign(const _Tuple_impl<_Idx, _UHead>& __in) const + { + _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in); + } + + template<typename _UHead> + constexpr void + _M_assign(_Tuple_impl<_Idx, _UHead>&& __in) const + { + _M_head(*this) + = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)); + } +#endif // C++23 + protected: _GLIBCXX20_CONSTEXPR void @@ -546,6 +667,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using std::swap; swap(_M_head(*this), _M_head(__in)); } + +#if __cplusplus > 202002L + constexpr void + _M_swap(const _Tuple_impl& __in) const + { + using std::swap; + swap(_M_head(*this), _M_head(__in)); + } +#endif // C++23 }; // Concept utility functions, reused in conditionally-explicit @@ -712,6 +842,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static constexpr bool __use_other_ctor() { return _UseOtherCtor<_Tuple>::value; } +#if __cplusplus > 202002L + template<typename... _Args> + static constexpr bool __constructible + = _TCC<true>::template __constructible<_Args...>::value; + + template<typename... _Args> + static constexpr bool __convertible + = _TCC<true>::template __convertible<_Args...>::value; +#endif // C++23 + public: template<typename _Dummy = void, _ImplicitDefaultCtor<is_void<_Dummy>::value> = true> @@ -799,6 +939,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION noexcept(__nothrow_constructible<_UElements...>()) : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { } +#if __cplusplus > 202002L + template<typename... _UElements> + requires (sizeof...(_Elements) == sizeof...(_UElements)) + && (!__use_other_ctor<tuple<_UElements...>&>()) + && __constructible<_UElements&...> + explicit(!__convertible<_UElements&...>) + constexpr + tuple(tuple<_UElements...>& __in) + noexcept(__nothrow_constructible<_UElements&...>()) + : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&>(__in)) + { } + + template<typename... _UElements> + requires (sizeof...(_Elements) == sizeof...(_UElements)) + && (!__use_other_ctor<const tuple<_UElements...>&&>()) + && __constructible<const _UElements...> + explicit(!__convertible<const _UElements...>) + constexpr + tuple(const tuple<_UElements...>&& __in) + noexcept(__nothrow_constructible<const _UElements...>()) + : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&&>(__in)) { } +#endif // C++23 + // Allocator-extended constructors. template<typename _Alloc, @@ -897,6 +1060,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { } +#if __cplusplus > 202002L + template<typename _Alloc, typename... _UElements> + requires (sizeof...(_Elements) == sizeof...(_UElements)) + && (!__use_other_ctor<tuple<_UElements...>&>()) + && __constructible<_UElements&...> + explicit(!__convertible<_UElements&...>) + constexpr + tuple(allocator_arg_t __tag, const _Alloc& __a, + tuple<_UElements...>& __in) + : _Inherited(__tag, __a, + static_cast<_Tuple_impl<0, _UElements...>&>(__in)) + { } + + template<typename _Alloc, typename... _UElements> + requires (sizeof...(_Elements) == sizeof...(_UElements)) + && (!__use_other_ctor<const tuple<_UElements...>>()) + && __constructible<const _UElements...> + explicit(!__convertible<const _UElements...>) + constexpr + tuple(allocator_arg_t __tag, const _Alloc& __a, + const tuple<_UElements...>&& __in) + : _Inherited(__tag, __a, + static_cast<const _Tuple_impl<0, _UElements...>&&>(__in)) + { } +#endif // C++23 + // tuple assignment _GLIBCXX20_CONSTEXPR @@ -941,12 +1130,57 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *this; } +#if __cplusplus > 202002L + constexpr const tuple& + operator=(const tuple& __in) const + requires (is_copy_assignable_v<const _Elements> && ...) + { + this->_M_assign(__in); + return *this; + } + + constexpr const tuple& + operator=(tuple&& __in) const + requires (is_assignable_v<const _Elements&, _Elements> && ...) + { + this->_M_assign(std::move(__in)); + return *this; + } + + template<typename... _UElements> + constexpr const tuple& + operator=(const tuple<_UElements...>& __in) const + requires (sizeof...(_Elements) == sizeof...(_UElements)) + && (is_assignable_v<const _Elements&, const _UElements&> && ...) + { + this->_M_assign(__in); + return *this; + } + + template<typename... _UElements> + constexpr const tuple& + operator=(tuple<_UElements...>&& __in) const + requires (sizeof...(_Elements) == sizeof...(_UElements)) + && (is_assignable_v<const _Elements&, _UElements> && ...) + { + this->_M_assign(std::move(__in)); + return *this; + } +#endif // C++23 + // tuple swap _GLIBCXX20_CONSTEXPR void swap(tuple& __in) noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value) { _Inherited::_M_swap(__in); } + +#if __cplusplus > 202002L + constexpr void + swap(const tuple& __in) const + noexcept(__and_v<__is_nothrow_swappable<const _Elements>...>) + { _Inherited::_M_swap(__in); } +#endif // C++23 }; #if __cpp_deduction_guides >= 201606 @@ -969,6 +1203,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION public: _GLIBCXX20_CONSTEXPR void swap(tuple&) noexcept { /* no-op */ } +#if __cplusplus > 202002L + constexpr void swap(const tuple&) const noexcept { /* no-op */ } +#endif // We need the default since we're going to define no-op // allocator constructors. tuple() = default; @@ -1048,6 +1285,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static constexpr bool __is_alloc_arg() { return is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value; } +#if __cplusplus > 202002L + template<typename _U1, typename _U2> + static constexpr bool __constructible + = _TCC<true>::template __constructible<_U1, _U2>::value; + + template<typename _U1, typename _U2> + static constexpr bool __convertible + = _TCC<true>::template __convertible<_U1, _U2>::value; +#endif // C++23 + public: template<bool _Dummy = true, _ImplicitDefaultCtor<_Dummy, _T1, _T2> = true> @@ -1123,6 +1370,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION noexcept(__nothrow_constructible<_U1, _U2>()) : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { } +#if __cplusplus > 202002L + template<typename _U1, typename _U2> + requires __constructible<_U1&, _U2&> + explicit(!__convertible<_U1&, _U2&>) + constexpr + tuple(tuple<_U1, _U2>& __in) + noexcept(__nothrow_constructible<_U1&, _U2&>()) + : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&>(__in)) { } + + template<typename _U1, typename _U2> + requires __constructible<const _U1, const _U2> + explicit(!__convertible<const _U1, const _U2>) + constexpr + tuple(const tuple<_U1, _U2>&& __in) + noexcept(__nothrow_constructible<const _U1, const _U2>()) + : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&&>(__in)) { } +#endif // C++23 + template<typename _U1, typename _U2, _ImplicitCtor<true, const _U1&, const _U2&> = true> constexpr @@ -1153,6 +1418,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _Inherited(std::forward<_U1>(__in.first), std::forward<_U2>(__in.second)) { } +#if __cplusplus > 202002L + template<typename _U1, typename _U2> + requires __constructible<_U1&, _U2&> + explicit(!__convertible<_U1&, _U2&>) + constexpr + tuple(pair<_U1, _U2>& __in) + noexcept(__nothrow_constructible<_U1&, _U2&>()) + : _Inherited(__in.first, __in.second) { } + + template<typename _U1, typename _U2> + requires __constructible<const _U1, const _U2> + explicit(!__convertible<const _U1, const _U2>) + constexpr + tuple(const pair<_U1, _U2>&& __in) + noexcept(__nothrow_constructible<const _U1, const _U2>()) + : _Inherited(std::forward<const _U1>(__in.first), + std::forward<const _U2>(__in.second)) { } +#endif // C++23 + // Allocator-extended constructors. template<typename _Alloc, @@ -1236,6 +1520,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { } +#if __cplusplus > 202002L + template<typename _Alloc, typename _U1, typename _U2> + requires __constructible<_U1&, _U2&> + explicit(!__convertible<_U1&, _U2&>) + constexpr + tuple(allocator_arg_t __tag, const _Alloc& __a, + tuple<_U1, _U2>& __in) + : _Inherited(__tag, __a, + static_cast<_Tuple_impl<0, _U1, _U2>&>(__in)) + { } + + template<typename _Alloc, typename _U1, typename _U2> + requires __constructible<const _U1, const _U2> + explicit(!__convertible<const _U1, const _U2>) + constexpr + tuple(allocator_arg_t __tag, const _Alloc& __a, + const tuple<_U1, _U2>&& __in) + : _Inherited(__tag, __a, + static_cast<const _Tuple_impl<0, _U1, _U2>&&>(__in)) + { } +#endif // C++23 + template<typename _Alloc, typename _U1, typename _U2, _ImplicitCtor<true, const _U1&, const _U2&> = true> _GLIBCXX20_CONSTEXPR @@ -1266,6 +1572,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _Inherited(__tag, __a, std::forward<_U1>(__in.first), std::forward<_U2>(__in.second)) { } +#if __cplusplus > 202002L + template<typename _Alloc, typename _U1, typename _U2> + requires __constructible<_U1&, _U2&> + explicit(!__convertible<_U1&, _U2&>) + constexpr + tuple(allocator_arg_t __tag, const _Alloc& __a, + pair<_U1, _U2>& __in) + : _Inherited(__tag, __a, __in.first, __in.second) { } + + template<typename _Alloc, typename _U1, typename _U2> + requires __constructible<const _U1, const _U2> + explicit(!__convertible<const _U1, const _U2>) + constexpr + tuple(allocator_arg_t __tag, const _Alloc& __a, const pair<_U1, _U2>&& __in) + : _Inherited(__tag, __a, std::forward<const _U1>(__in.first), + std::forward<const _U2>(__in.second)) { } +#endif // C++23 + // Tuple assignment. _GLIBCXX20_CONSTEXPR @@ -1310,6 +1634,44 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *this; } +#if __cplusplus > 202002L + constexpr const tuple& + operator=(const tuple& __in) const + requires is_copy_assignable_v<const _T1> && is_copy_assignable_v<const _T2> + { + this->_M_assign(__in); + return *this; + } + + constexpr const tuple& + operator=(tuple&& __in) const + requires is_assignable_v<const _T1&, _T1> && is_assignable_v<const _T2, _T2> + { + this->_M_assign(std::move(__in)); + return *this; + } + + template<typename _U1, typename _U2> + constexpr const tuple& + operator=(const tuple<_U1, _U2>& __in) const + requires is_assignable_v<const _T1&, const _U1&> + && is_assignable_v<const _T2&, const _U2&> + { + this->_M_assign(__in); + return *this; + } + + template<typename _U1, typename _U2> + constexpr const tuple& + operator=(tuple<_U1, _U2>&& __in) const + requires is_assignable_v<const _T1&, _U1> + && is_assignable_v<const _T2&, _U2> + { + this->_M_assign(std::move(__in)); + return *this; + } +#endif // C++23 + template<typename _U1, typename _U2> _GLIBCXX20_CONSTEXPR __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&> @@ -1332,12 +1694,44 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *this; } +#if __cplusplus > 202002L + template<typename _U1, typename _U2> + constexpr const tuple& + operator=(const pair<_U1, _U2>& __in) const + requires is_assignable_v<const _T1&, const _U1&> + && is_assignable_v<const _T2&, const _U2&> + { + this->_M_head(*this) = __in.first; + this->_M_tail(*this)._M_head(*this) = __in.second; + return *this; + } + + template<typename _U1, typename _U2> + constexpr const tuple& + operator=(pair<_U1, _U2>&& __in) const + requires is_assignable_v<const _T1&, _U1> + && is_assignable_v<const _T2&, _U2> + { + this->_M_head(*this) = std::forward<_U1>(__in.first); + this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second); + return *this; + } +#endif // C++23 + _GLIBCXX20_CONSTEXPR void swap(tuple& __in) noexcept(__and_<__is_nothrow_swappable<_T1>, __is_nothrow_swappable<_T2>>::value) { _Inherited::_M_swap(__in); } + +#if __cplusplus > 202002L + constexpr void + swap(const tuple& __in) const + noexcept(__and_v<__is_nothrow_swappable<const _T1>, + __is_nothrow_swappable<const _T2>>) + { _Inherited::_M_swap(__in); } +#endif // C++23 }; @@ -1765,6 +2159,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION noexcept(noexcept(__x.swap(__y))) { __x.swap(__y); } +#if __cplusplus > 202002L + template<typename... _Elements> + requires (is_swappable_v<const _Elements> && ...) + constexpr void + swap(const tuple<_Elements...>& __x, const tuple<_Elements...>& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } +#endif // C++23 + #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 template<typename... _Elements> _GLIBCXX20_CONSTEXPR @@ -1889,6 +2292,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #endif // C++17 +#if __cplusplus > 202002L + template<typename... _TTypes, typename... _UTypes, + template<typename> class TQual, template<typename> class UQual> + requires requires { typename tuple<common_reference_t<TQual<_TTypes>, UQual<_UTypes>>...>; } + struct basic_common_reference<tuple<_TTypes...>, tuple<_UTypes...>, TQual, UQual> + { using type = tuple<common_reference_t<TQual<_TTypes>, UQual<_UTypes>>...>; }; + + template<typename... _TTypes, typename... _UTypes> + requires requires { typename tuple<common_type_t<_TTypes, _UTypes>...>; } + struct common_type<tuple<_TTypes...>, tuple<_UTypes...>> + { using type = tuple<common_type_t<_TTypes, _UTypes>...>; }; +#endif // C++23 + /// @} _GLIBCXX_END_NAMESPACE_VERSION |