DPC++ Runtime
Runtime libraries for oneAPI DPC++
tuple.hpp
Go to the documentation of this file.
1 //== tuple.hpp - limited trivially copy constructible implementation- 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-exception
6 //
7 // ===--------------------------------------------------------------------=== //
8 
9 #pragma once
10 
11 #include <array> // for tuple_element
12 #include <cstddef> // for size_t
13 #include <tuple> // for tuple
14 #include <utility> // for make_index_sequence, index_sequence
15 #include <variant> // for tuple
16 
17 namespace sycl {
18 inline namespace _V1 {
19 namespace detail {
20 
21 template <typename... T> struct tuple;
22 
23 template <typename T, typename... Ts, std::size_t... Is>
24 std::tuple<Ts...> get_tuple_tail_impl(const std::tuple<T, Ts...> &Tuple,
25  const std::index_sequence<Is...> &) {
26  return std::tuple<Ts...>(std::get<Is + 1>(Tuple)...);
27 }
28 
29 template <typename T, typename... Ts>
30 std::tuple<Ts...> get_tuple_tail(const std::tuple<T, Ts...> &Tuple) {
32  Tuple, std::make_index_sequence<sizeof...(Ts)>());
33 }
34 
35 template <typename... Ts> constexpr tuple<Ts...> make_tuple(Ts... Args) {
36  return sycl::detail::tuple<Ts...>{Args...};
37 }
38 
39 template <typename... Ts> auto tie(Ts &...Args) {
40  return sycl::detail::tuple<Ts &...>(Args...);
41 }
42 
43 template <std::size_t N, typename T> struct tuple_element;
44 
45 template <std::size_t N, typename T, typename... Rest>
46 struct tuple_element<N, tuple<T, Rest...>>
47  : tuple_element<N - 1, tuple<Rest...>> {};
48 
49 template <typename T, typename... Rest>
50 struct tuple_element<0, tuple<T, Rest...>> {
51  using type = T;
52 };
53 
54 template <std::size_t I, class T>
56 
57 // Functor returning reference to the selected element of the tuple.
58 template <size_t N> struct get {
59  template <typename... Ts>
60  constexpr auto operator()(tuple<Ts...> &Tuple) const
61  -> decltype(get<N - 1>()(Tuple.next)) {
62  return get<N - 1>()(Tuple.next);
63  }
64 
65  template <typename... Ts>
66  constexpr auto operator()(const tuple<Ts...> &Tuple) const
67  -> decltype(get<N - 1>()(Tuple.next)) {
68  return get<N - 1>()(Tuple.next);
69  }
70 };
71 
72 // Functor returning reference to selected element of the tuple.
73 // Specialization stopping the recursion.
74 template <> struct get<0> {
75  template <typename... Ts>
76  using ret_type = typename tuple_element<0, tuple<Ts...>>::type;
77 
78  template <typename... Ts>
79  constexpr ret_type<Ts...> &operator()(tuple<Ts...> &Tuple) const noexcept {
80  return Tuple.holder.value;
81  }
82 
83  template <typename... Ts>
84  constexpr ret_type<Ts...> const &
85  operator()(const tuple<Ts...> &Tuple) const noexcept {
86  return Tuple.holder.value;
87  }
88 };
89 
90 template <typename T> struct TupleValueHolder {
91  TupleValueHolder() = default;
92  TupleValueHolder(const T &Value) : value(Value) {}
93  T value;
94 };
95 
96 // Tuple needs to be trivially_copy_assignable. Define operator= if necessary.
97 template <typename T,
98  bool = std::is_trivially_copy_assignable_v<TupleValueHolder<T>>>
101 };
102 
103 template <typename T>
106 
109  this->value = RHS.value;
110  return *this;
111  }
112 };
113 
114 template <typename T, typename... Ts> struct tuple<T, Ts...> {
116  tuple<Ts...> next;
117 
118  using tuple_type = std::tuple<T, Ts...>;
119 
120  tuple() = default;
121  tuple(const tuple &) = default;
122  template <typename UT, typename... UTs>
124  : holder(RHS.holder.value), next(RHS.next) {}
125 
126  tuple(const T &Value, const Ts &...Next) : holder(Value), next(Next...) {}
127 
128  // required to convert std::tuple to inner tuple in user-provided functor
129  tuple(const std::tuple<T, Ts...> &RHS)
130  : holder(std::get<0>(RHS)), next(sycl::detail::get_tuple_tail(RHS)) {}
131 
132  // Convert to std::tuple with the same template arguments.
133  operator std::tuple<T, Ts...>() const {
134  return to_std_tuple(*this, std::make_index_sequence<sizeof...(Ts) + 1>());
135  }
136 
137  // Convert to std::tuple with different template arguments.
138  template <typename UT, typename... UTs>
139  operator std::tuple<UT, UTs...>() const {
140  return to_std_tuple(static_cast<tuple<UT, UTs...>>(*this),
141  std::make_index_sequence<sizeof...(Ts) + 1>());
142  }
143 
144  template <typename UT, typename... UTs>
146  holder.value = RHS.holder.value;
147  next = RHS.next;
148  return *this;
149  }
150 
151  // if T is deduced with reference, compiler generates deleted operator= and,
152  // since "template operator=" is not considered as operator= overload
153  // the deleted operator= has a preference during lookup
155 
156  // Convert std::tuple to sycl::detail::tuple
157  template <typename UT, typename... UTs>
158  tuple &operator=(const std::tuple<UT, UTs...> &RHS) {
159  holder.value = std::get<0>(RHS);
160  next = sycl::detail::get_tuple_tail(RHS);
161  return *this;
162  }
163 
164  friend bool operator==(const tuple &LHS, const tuple &RHS) {
165  return LHS.holder.value == RHS.holder.value && LHS.next == RHS.next;
166  }
167  friend bool operator!=(const tuple &LHS, const tuple &RHS) {
168  return !(LHS == RHS);
169  }
170 
171  template <typename UT, typename... UTs, std::size_t... Is>
172  static std::tuple<UT, UTs...> to_std_tuple(const tuple<UT, UTs...> &Tuple,
173  std::index_sequence<Is...>) {
174  return std::tuple<UT, UTs...>(get<Is>()(Tuple)...);
175  }
176 };
177 
178 template <> struct tuple<> {
179  using tuple_type = std::tuple<>;
180 
181  tuple() = default;
182  tuple(const tuple &) = default;
183  tuple(const std::tuple<> &) {}
184 
185  tuple &operator=(const tuple &) = default;
186  tuple &operator=(const std::tuple<> &) { return *this; }
187  friend bool operator==(const tuple &, const tuple &) { return true; }
188 };
189 
190 } // namespace detail
191 } // namespace _V1
192 } // namespace sycl
193 
194 namespace std {
195 
196 template <size_t I, typename... Types>
197 constexpr typename tuple_element<I, tuple<Types...>>::type &
198 get(sycl::detail::tuple<Types...> &Arg) noexcept {
199  return sycl::detail::get<I>()(Arg);
200 }
201 
202 template <size_t I, typename... Types>
203 constexpr typename tuple_element<I, tuple<Types...>>::type const &
204 get(const sycl::detail::tuple<Types...> &Arg) noexcept {
205  return sycl::detail::get<I>()(Arg);
206 }
207 
208 } // namespace std
constexpr tuple_element< I, tuple< Types... > >::type & get(sycl::detail::tuple< Types... > &Arg) noexcept
Definition: tuple.hpp:198
std::tuple< Ts... > get_tuple_tail(const std::tuple< T, Ts... > &Tuple)
Definition: tuple.hpp:30
std::tuple< Ts... > get_tuple_tail_impl(const std::tuple< T, Ts... > &Tuple, const std::index_sequence< Is... > &)
Definition: tuple.hpp:24
constexpr tuple< Ts... > make_tuple(Ts... Args)
Definition: tuple.hpp:35
auto tie(Ts &...Args)
Definition: tuple.hpp:39
typename tuple_element< I, T >::type tuple_element_t
Definition: tuple.hpp:55
Definition: access.hpp:18
_Abi const simd< _Tp, _Abi > & noexcept
Definition: simd.hpp:1324
TupleCopyAssignableValueHolder & operator=(const TupleCopyAssignableValueHolder &RHS)
Definition: tuple.hpp:108
TupleValueHolder(const T &Value)
Definition: tuple.hpp:92
typename tuple_element< 0, tuple< Ts... > >::type ret_type
Definition: tuple.hpp:76
constexpr ret_type< Ts... > const & operator()(const tuple< Ts... > &Tuple) const noexcept
Definition: tuple.hpp:85
constexpr ret_type< Ts... > & operator()(tuple< Ts... > &Tuple) const noexcept
Definition: tuple.hpp:79
constexpr auto operator()(const tuple< Ts... > &Tuple) const -> decltype(get< N - 1 >()(Tuple.next))
Definition: tuple.hpp:66
constexpr auto operator()(tuple< Ts... > &Tuple) const -> decltype(get< N - 1 >()(Tuple.next))
Definition: tuple.hpp:60
tuple & operator=(const detail::tuple< T, Ts... > &)=default
TupleCopyAssignableValueHolder< T > holder
Definition: tuple.hpp:115
std::tuple< T, Ts... > tuple_type
Definition: tuple.hpp:118
friend bool operator==(const tuple &LHS, const tuple &RHS)
Definition: tuple.hpp:164
static std::tuple< UT, UTs... > to_std_tuple(const tuple< UT, UTs... > &Tuple, std::index_sequence< Is... >)
Definition: tuple.hpp:172
tuple(const std::tuple< T, Ts... > &RHS)
Definition: tuple.hpp:129
tuple & operator=(const detail::tuple< UT, UTs... > &RHS)
Definition: tuple.hpp:145
tuple(const tuple< UT, UTs... > &RHS)
Definition: tuple.hpp:123
tuple & operator=(const std::tuple< UT, UTs... > &RHS)
Definition: tuple.hpp:158
friend bool operator!=(const tuple &LHS, const tuple &RHS)
Definition: tuple.hpp:167
tuple(const T &Value, const Ts &...Next)
Definition: tuple.hpp:126
tuple & operator=(const tuple &)=default
tuple(const std::tuple<> &)
Definition: tuple.hpp:183
std::tuple<> tuple_type
Definition: tuple.hpp:179
friend bool operator==(const tuple &, const tuple &)
Definition: tuple.hpp:187
tuple(const tuple &)=default
tuple & operator=(const std::tuple<> &)
Definition: tuple.hpp:186