chromium/third_party/libc++/src/include/tuple

// -*- 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