// -*- C++ -*- //===----------------------------------------------------------------------===// // // 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 #define _LIBCPP_TUPLE // clang-format off /* tuple synopsis namespace std { template <class... T> class tuple { public: 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 tuple(const tuple&) = default; tuple(tuple&&) = default; template<class... UTypes> constexpr explicit(see-below) tuple(tuple<UTypes...>&); // C++23 template <class... U> explicit(see-below) tuple(const tuple<U...>&); // constexpr in C++14 template <class... U> explicit(see-below) tuple(tuple<U...>&&); // constexpr in C++14 template<class... UTypes> constexpr explicit(see-below) tuple(const tuple<UTypes...>&&); // C++23 template<class U1, class U2> constexpr explicit(see-below) tuple(pair<U1, U2>&); // iff sizeof...(Types) == 2 // C++23 template <class U1, class U2> explicit(see-below) tuple(const pair<U1, U2>&); // iff sizeof...(T) == 2 // constexpr in C++14 template <class U1, class U2> explicit(see-below) tuple(pair<U1, U2>&&); // iff sizeof...(T) == 2 // constexpr in C++14 template<class U1, class U2> constexpr explicit(see-below) tuple(const pair<U1, U2>&&); // iff sizeof...(Types) == 2 // C++23 // allocator-extended constructors template <class Alloc> tuple(allocator_arg_t, const Alloc& a); template <class Alloc> explicit(see-below) tuple(allocator_arg_t, const Alloc& a, const T&...); // constexpr in C++20 template <class Alloc, class... U> explicit(see-below) tuple(allocator_arg_t, const Alloc& a, U&&...); // constexpr in C++20 template <class Alloc> tuple(allocator_arg_t, const Alloc& a, const tuple&); // constexpr in C++20 template <class Alloc> tuple(allocator_arg_t, const Alloc& a, tuple&&); // constexpr in C++20 template<class Alloc, class... UTypes> constexpr explicit(see-below) tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&); // C++23 template <class Alloc, class... U> explicit(see-below) tuple(allocator_arg_t, const Alloc& a, const tuple<U...>&); // constexpr in C++20 template <class Alloc, class... U> explicit(see-below) tuple(allocator_arg_t, const Alloc& a, tuple<U...>&&); // constexpr in C++20 template<class Alloc, class... UTypes> constexpr explicit(see-below) tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&&); // C++23 template<class Alloc, class U1, class U2> constexpr explicit(see-below) tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&); // C++23 template <class Alloc, class U1, class U2> explicit(see-below) tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&); // constexpr in C++20 template <class Alloc, class U1, class U2> explicit(see-below) tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&); // constexpr in C++20 template<class Alloc, class U1, class U2> constexpr explicit(see-below) tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&&); // C++23 tuple& operator=(const tuple&); // constexpr in C++20 constexpr const tuple& operator=(const tuple&) const; // C++23 tuple& operator=(tuple&&) noexcept(is_nothrow_move_assignable_v<T> && ...); // constexpr in C++20 constexpr const tuple& operator=(tuple&&) const; // C++23 template <class... U> tuple& operator=(const tuple<U...>&); // constexpr in C++20 template<class... UTypes> constexpr const tuple& operator=(const tuple<UTypes...>&) const; // C++23 template <class... U> tuple& operator=(tuple<U...>&&); // constexpr in C++20 template<class... UTypes> constexpr const tuple& operator=(tuple<UTypes...>&&) const; // C++23 template <class U1, class U2> tuple& operator=(const pair<U1, U2>&); // iff sizeof...(T) == 2 // constexpr in C++20 template<class U1, class U2> constexpr const tuple& operator=(const pair<U1, U2>&) const; // iff sizeof...(Types) == 2 // C++23 template <class U1, class U2> tuple& operator=(pair<U1, U2>&&); // iff sizeof...(T) == 2 // constexpr in C++20 template<class U1, class U2> constexpr const tuple& operator=(pair<U1, U2>&&) const; // iff sizeof...(Types) == 2 // C++23 template<class U, size_t N> tuple& operator=(array<U, N> const&) // iff sizeof...(T) == N, EXTENSION template<class U, size_t N> tuple& operator=(array<U, N>&&) // iff sizeof...(T) == N, EXTENSION void swap(tuple&) noexcept(AND(swap(declval<T&>(), declval<T&>())...)); // constexpr in C++20 constexpr void swap(const tuple&) const noexcept(see-below); // C++23 }; template<class... TTypes, class... UTypes, template<class> class TQual, template<class> class UQual> // since C++23 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<class... TTypes, class... UTypes> // since C++23 requires requires { typename tuple<common_type_t<TTypes, UTypes>...>; } struct common_type<tuple<TTypes...>, tuple<UTypes...>> { using type = tuple<common_type_t<TTypes, UTypes>...>; }; template <class ...T> tuple(T...) -> tuple<T...>; // since C++17 template <class T1, class T2> tuple(pair<T1, T2>) -> tuple<T1, T2>; // since C++17 template <class Alloc, class ...T> tuple(allocator_arg_t, Alloc, T...) -> tuple<T...>; // since C++17 template <class Alloc, class T1, class T2> tuple(allocator_arg_t, Alloc, pair<T1, T2>) -> tuple<T1, T2>; // since C++17 template <class Alloc, class ...T> tuple(allocator_arg_t, Alloc, tuple<T...>) -> tuple<T...>; // since C++17 struct ignore-type { // exposition only // Since C++26 constexpr const ignore-type& operator=(const auto &) const noexcept { return *this; } }; inline constexpr ignore-type ignore; template <class... T> tuple<V...> make_tuple(T&&...); // constexpr in C++14 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) noexcept(see below); // C++17 noexcept since C++23 template <class T, class Tuple> constexpr T make_from_tuple(Tuple&& t); // C++17 // 20.4.1.4, tuple helper classes: template <class T> struct tuple_size; // undefined template <class... T> struct tuple_size<tuple<T...>>; template <class T> inline constexpr size_t tuple_size_v = tuple_size<T>::value; // C++17 template <size_t I, class T> struct tuple_element; // undefined template <size_t I, class... T> struct tuple_element<I, tuple<T...>>; template <size_t I, class T> using tuple_element_t = typename tuple_element <I, T>::type; // C++14 // 20.4.1.5, element access: template <size_t I, class... T> typename tuple_element<I, tuple<T...>>::type& get(tuple<T...>&) noexcept; // constexpr in C++14 template <size_t I, class... T> const typename tuple_element<I, tuple<T...>>::type& get(const tuple<T...>&) noexcept; // constexpr in C++14 template <size_t I, class... T> typename tuple_element<I, tuple<T...>>::type&& get(tuple<T...>&&) noexcept; // constexpr in C++14 template <size_t I, class... T> const typename tuple_element<I, tuple<T...>>::type&& get(const tuple<T...>&&) noexcept; // constexpr in C++14 template <class T1, class... T> constexpr T1& get(tuple<T...>&) noexcept; // C++14 template <class T1, class... T> constexpr const T1& get(const tuple<T...>&) noexcept; // C++14 template <class T1, class... T> constexpr T1&& get(tuple<T...>&&) noexcept; // C++14 template <class T1, class... T> constexpr const T1&& get(const tuple<T...>&&) noexcept; // C++14 // 20.4.1.6, relational operators: template<class... T, class... U> bool operator==(const tuple<T...>&, const tuple<U...>&); // constexpr in C++14 template<class... T, class... U> bool operator<(const tuple<T...>&, const tuple<U...>&); // constexpr in C++14, removed in C++20 template<class... T, class... U> bool operator!=(const tuple<T...>&, const tuple<U...>&); // constexpr in C++14, removed in C++20 template<class... T, class... U> bool operator>(const tuple<T...>&, const tuple<U...>&); // constexpr in C++14, removed in C++20 template<class... T, class... U> bool operator<=(const tuple<T...>&, const tuple<U...>&); // constexpr in C++14, removed in C++20 template<class... T, class... U> bool operator>=(const tuple<T...>&, const tuple<U...>&); // constexpr in C++14, removed in C++20 template<class... T, class... U> constexpr common_comparison_category_t<synth-three-way-result<T, U>...> operator<=>(const tuple<T...>&, const tuple<U...>&); // since C++20 template <class... Types, class Alloc> struct uses_allocator<tuple<Types...>, Alloc>; template <class... Types> void swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(noexcept(x.swap(y))); template <class... Types> constexpr void swap(const tuple<Types...>& x, const tuple<Types...>& y) noexcept(see-below); // C++23 } // std */ // clang-format on #include <__compare/common_comparison_category.h> #include <__compare/synth_three_way.h> #include <__config> #include <__functional/invoke.h> #include <__fwd/array.h> #include <__fwd/pair.h> #include <__fwd/tuple.h> #include <__memory/allocator_arg_t.h> #include <__memory/uses_allocator.h> #include <__tuple/find_index.h> #include <__tuple/ignore.h> #include <__tuple/make_tuple_types.h> #include <__tuple/sfinae_helpers.h> #include <__tuple/tuple_element.h> #include <__tuple/tuple_indices.h> #include <__tuple/tuple_like_ext.h> #include <__tuple/tuple_size.h> #include <__tuple/tuple_types.h> #include <__type_traits/common_reference.h> #include <__type_traits/common_type.h> #include <__type_traits/conditional.h> #include <__type_traits/conjunction.h> #include <__type_traits/copy_cvref.h> #include <__type_traits/disjunction.h> #include <__type_traits/is_arithmetic.h> #include <__type_traits/is_assignable.h> #include <__type_traits/is_constructible.h> #include <__type_traits/is_convertible.h> #include <__type_traits/is_empty.h> #include <__type_traits/is_final.h> #include <__type_traits/is_implicitly_default_constructible.h> #include <__type_traits/is_nothrow_assignable.h> #include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/is_reference.h> #include <__type_traits/is_same.h> #include <__type_traits/is_swappable.h> #include <__type_traits/is_trivially_relocatable.h> #include <__type_traits/lazy.h> #include <__type_traits/maybe_const.h> #include <__type_traits/nat.h> #include <__type_traits/negation.h> #include <__type_traits/remove_cvref.h> #include <__type_traits/remove_reference.h> #include <__type_traits/unwrap_ref.h> #include <__utility/forward.h> #include <__utility/integer_sequence.h> #include <__utility/move.h> #include <__utility/piecewise_construct.h> #include <__utility/swap.h> #include <cstddef> #include <version> // standard-mandated includes // [tuple.syn] #include <compare> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif _LIBCPP_PUSH_MACROS #include <__undef_macros> _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_POP_MACROS // clang-format on #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <exception> # include <iosfwd> # include <new> # include <type_traits> # include <typeinfo> # include <utility> #endif #endif // _LIBCPP_TUPLE