brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.9 KiB · fa4fcd0 Raw
145 lines · c
1//===-- tuple utility -------------------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_TUPLE_H10#define LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_TUPLE_H11 12#include "src/__support/CPP/type_traits/decay.h"13#include "src/__support/CPP/utility/integer_sequence.h"14 15namespace LIBC_NAMESPACE_DECL {16namespace cpp {17 18template <typename... Ts> struct tuple;19template <> struct tuple<> {};20 21template <typename Head, typename... Tail>22struct tuple<Head, Tail...> : tuple<Tail...> {23  Head head;24 25  LIBC_INLINE constexpr tuple() = default;26 27  template <typename OHead, typename... OTail>28  LIBC_INLINE constexpr tuple &operator=(const tuple<OHead, OTail...> &other) {29    head = other.get_head();30    this->get_tail() = other.get_tail();31    return *this;32  }33 34  LIBC_INLINE constexpr tuple(const Head &h, const Tail &...t)35      : tuple<Tail...>(t...), head(h) {}36 37  LIBC_INLINE constexpr Head &get_head() { return head; }38  LIBC_INLINE constexpr const Head &get_head() const { return head; }39 40  LIBC_INLINE constexpr tuple<Tail...> &get_tail() { return *this; }41  LIBC_INLINE constexpr const tuple<Tail...> &get_tail() const { return *this; }42};43 44template <typename... Ts> LIBC_INLINE constexpr auto make_tuple(Ts &&...args) {45  return tuple<cpp::decay_t<Ts>...>(static_cast<Ts &&>(args)...);46}47template <typename... Ts> LIBC_INLINE constexpr auto tie(Ts &...args) {48  return tuple<Ts &...>(args...);49}50 51template <size_t Idx, typename Head, typename... Tail>52LIBC_INLINE constexpr auto &get(tuple<Head, Tail...> &t) {53  if constexpr (Idx == 0)54    return t.get_head();55  else56    return get<Idx - 1>(t.get_tail());57}58template <size_t Idx, typename Head, typename... Tail>59LIBC_INLINE constexpr const auto &get(const tuple<Head, Tail...> &t) {60  if constexpr (Idx == 0)61    return t.get_head();62  else63    return get<Idx - 1>(t.get_tail());64}65template <size_t Idx, typename Head, typename... Tail>66LIBC_INLINE constexpr auto &&get(tuple<Head, Tail...> &&t) {67  if constexpr (Idx == 0)68    return static_cast<Head &&>(t.get_head());69  else70    return get<Idx - 1>(static_cast<tuple<Tail...> &&>(t.get_tail()));71}72template <size_t Idx, typename Head, typename... Tail>73LIBC_INLINE constexpr const auto &&get(const tuple<Head, Tail...> &&t) {74  if constexpr (Idx == 0)75    return static_cast<const Head &&>(t.get_head());76  else77    return get<Idx - 1>(static_cast<const tuple<Tail...> &&>(t.get_tail()));78}79 80template <typename T> struct tuple_size;81template <typename... Ts> struct tuple_size<tuple<Ts...>> {82  static constexpr size_t value = sizeof...(Ts);83};84 85template <size_t Idx, typename T> struct tuple_element;86template <size_t Idx, typename Head, typename... Tail>87struct tuple_element<Idx, tuple<Head, Tail...>>88    : tuple_element<Idx - 1, tuple<Tail...>> {};89template <typename Head, typename... Tail>90struct tuple_element<0, tuple<Head, Tail...>> {91  using type = cpp::remove_cv_t<cpp::remove_reference_t<Head>>;92};93 94namespace internal {95template <typename... As, typename... Bs, size_t... Idx, size_t... J>96LIBC_INLINE constexpr auto97tuple_cat(const tuple<As...> &a, const tuple<Bs...> &b,98          cpp::index_sequence<Idx...>, cpp::index_sequence<J...>) {99  return tuple<As..., Bs...>(get<Idx>(a)..., get<J>(b)...);100}101 102template <typename First, typename Second, typename... Rest>103LIBC_INLINE constexpr auto tuple_cat(const First &f, const Second &s,104                                     const Rest &...rest) {105  auto concat =106      tuple_cat(f, s, cpp::make_index_sequence<tuple_size<First>::value>{},107                cpp::make_index_sequence<tuple_size<Second>::value>{});108  if constexpr (sizeof...(Rest))109    return tuple_cat(concat, rest...);110  else111    return concat;112}113} // namespace internal114 115template <typename... Tuples>116LIBC_INLINE constexpr auto tuple_cat(const Tuples &...tuples) {117  static_assert(sizeof...(Tuples) > 0, "need at least one element");118  if constexpr (sizeof...(Tuples) == 1)119    return (tuples, ...);120  else121    return internal::tuple_cat(tuples...);122}123 124} // namespace cpp125} // namespace LIBC_NAMESPACE_DECL126 127// Standard namespace definitions required for structured binding support.128namespace std {129 130template <class T> struct tuple_size;131template <size_t Idx, class T> struct tuple_element;132 133template <typename... Ts>134struct tuple_size<LIBC_NAMESPACE::cpp::tuple<Ts...>>135    : LIBC_NAMESPACE::cpp::tuple_size<LIBC_NAMESPACE::cpp::tuple<Ts...>> {};136 137template <size_t Idx, typename... Ts>138struct tuple_element<Idx, LIBC_NAMESPACE::cpp::tuple<Ts...>>139    : LIBC_NAMESPACE::cpp::tuple_element<Idx,140                                         LIBC_NAMESPACE::cpp::tuple<Ts...>> {};141 142} // namespace std143 144#endif // LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_TUPLE_H145