Eigen  5.0.1-dev+284dcc12
 
Loading...
Searching...
No Matches
Tuple.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2021 The Eigen Team
5//
6// This Source Code Form is subject to the terms of the Mozilla
7// Public License v. 2.0. If a copy of the MPL was not distributed
8// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
10#ifndef EIGEN_TUPLE_GPU
11#define EIGEN_TUPLE_GPU
12
13#include <type_traits>
14#include <utility>
15
16// This is a replacement of std::tuple that can be used in device code.
17
18namespace Eigen {
19namespace internal {
20namespace tuple_impl {
21
22// Internal tuple implementation.
23template <size_t N, typename... Types>
24class TupleImpl;
25
26// Generic recursive tuple.
27template <size_t N, typename T1, typename... Ts>
28class TupleImpl<N, T1, Ts...> {
29 public:
30 // Tuple may contain Eigen types.
31 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
32
33 // Default constructor, enable if all types are default-constructible.
34 template <typename U1 = T1,
35 typename EnableIf = std::enable_if_t<std::is_default_constructible<U1>::value &&
36 reduce_all<std::is_default_constructible<Ts>::value...>::value>>
37 constexpr EIGEN_DEVICE_FUNC TupleImpl() : head_{}, tail_{} {}
38
39 // Element constructor.
40 template <typename U1, typename... Us,
41 // Only enable if...
42 typename EnableIf = std::enable_if_t<
43 // the number of input arguments match, and ...
44 sizeof...(Us) == sizeof...(Ts) && (
45 // this does not look like a copy/move constructor.
46 N > 1 || std::is_convertible<U1, T1>::value)>>
47 constexpr EIGEN_DEVICE_FUNC TupleImpl(U1&& arg1, Us&&... args)
48 : head_(std::forward<U1>(arg1)), tail_(std::forward<Us>(args)...) {}
49
50 // The first stored value.
51 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T1& head() { return head_; }
52
53 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE const T1& head() const { return head_; }
54
55 // The tail values.
56 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE TupleImpl<N - 1, Ts...>& tail() { return tail_; }
57
58 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE const TupleImpl<N - 1, Ts...>& tail() const { return tail_; }
59
60 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void swap(TupleImpl& other) {
61 using numext::swap;
62 swap(head_, other.head_);
63 swap(tail_, other.tail_);
64 }
65
66 template <typename... UTypes>
67 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TupleImpl& operator=(const TupleImpl<N, UTypes...>& other) {
68 head_ = other.head_;
69 tail_ = other.tail_;
70 return *this;
71 }
72
73 template <typename... UTypes>
74 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TupleImpl& operator=(TupleImpl<N, UTypes...>&& other) {
75 head_ = std::move(other.head_);
76 tail_ = std::move(other.tail_);
77 return *this;
78 }
79
80 private:
81 // Allow related tuples to reference head_/tail_.
82 template <size_t M, typename... UTypes>
83 friend class TupleImpl;
84
85 T1 head_;
86 TupleImpl<N - 1, Ts...> tail_;
87};
88
89// Empty tuple specialization.
90template <>
91class TupleImpl<size_t(0)> {};
92
93template <typename TupleType>
94struct is_tuple : std::false_type {};
95
96template <typename... Types>
97struct is_tuple<TupleImpl<sizeof...(Types), Types...>> : std::true_type {};
98
99// Gets an element from a tuple.
100template <size_t Idx, typename T1, typename... Ts>
101struct tuple_get_impl {
102 using TupleType = TupleImpl<sizeof...(Ts) + 1, T1, Ts...>;
103 using ReturnType = typename tuple_get_impl<Idx - 1, Ts...>::ReturnType;
104
105 static constexpr EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE ReturnType& run(TupleType& tuple) {
106 return tuple_get_impl<Idx - 1, Ts...>::run(tuple.tail());
107 }
108
109 static constexpr EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE const ReturnType& run(const TupleType& tuple) {
110 return tuple_get_impl<Idx - 1, Ts...>::run(tuple.tail());
111 }
112};
113
114// Base case, getting the head element.
115template <typename T1, typename... Ts>
116struct tuple_get_impl<0, T1, Ts...> {
117 using TupleType = TupleImpl<sizeof...(Ts) + 1, T1, Ts...>;
118 using ReturnType = T1;
119
120 static constexpr EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T1& run(TupleType& tuple) { return tuple.head(); }
121
122 static constexpr EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE const T1& run(const TupleType& tuple) { return tuple.head(); }
123};
124
125// Concatenates N Tuples.
126template <size_t NTuples, typename... Tuples>
127struct tuple_cat_impl;
128
129template <size_t NTuples, size_t N1, typename... Args1, size_t N2, typename... Args2, typename... Tuples>
130struct tuple_cat_impl<NTuples, TupleImpl<N1, Args1...>, TupleImpl<N2, Args2...>, Tuples...> {
131 using TupleType1 = TupleImpl<N1, Args1...>;
132 using TupleType2 = TupleImpl<N2, Args2...>;
133 using MergedTupleType = TupleImpl<N1 + N2, Args1..., Args2...>;
134
135 using ReturnType = typename tuple_cat_impl<NTuples - 1, MergedTupleType, Tuples...>::ReturnType;
136
137 // Uses the index sequences to extract and merge elements from tuple1 and tuple2,
138 // then recursively calls again.
139 template <typename Tuple1, size_t... I1s, typename Tuple2, size_t... I2s, typename... MoreTuples>
140 static constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ReturnType run(Tuple1&& tuple1, std::index_sequence<I1s...>,
141 Tuple2&& tuple2, std::index_sequence<I2s...>,
142 MoreTuples&&... tuples) {
143 return tuple_cat_impl<NTuples - 1, MergedTupleType, Tuples...>::run(
144 MergedTupleType(tuple_get_impl<I1s, Args1...>::run(std::forward<Tuple1>(tuple1))...,
145 tuple_get_impl<I2s, Args2...>::run(std::forward<Tuple2>(tuple2))...),
146 std::forward<MoreTuples>(tuples)...);
147 }
148
149 // Concatenates the first two tuples.
150 template <typename Tuple1, typename Tuple2, typename... MoreTuples>
151 static constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ReturnType run(Tuple1&& tuple1, Tuple2&& tuple2,
152 MoreTuples&&... tuples) {
153 return run(std::forward<Tuple1>(tuple1), std::make_index_sequence<N1>{}, std::forward<Tuple2>(tuple2),
154 std::make_index_sequence<N2>{}, std::forward<MoreTuples>(tuples)...);
155 }
156};
157
158// Base case with a single tuple.
159template <size_t N, typename... Args>
160struct tuple_cat_impl<1, TupleImpl<N, Args...>> {
161 using ReturnType = TupleImpl<N, Args...>;
162
163 template <typename Tuple1>
164 static constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ReturnType run(Tuple1&& tuple1) {
165 return tuple1;
166 }
167};
168
169// Special case of no tuples.
170template <>
171struct tuple_cat_impl<0> {
172 using ReturnType = TupleImpl<0>;
173 static constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ReturnType run() { return ReturnType{}; }
174};
175
176// For use in make_tuple, unwraps a reference_wrapper.
177template <typename T>
178struct unwrap_reference_wrapper {
179 using type = T;
180};
181
182template <typename T>
183struct unwrap_reference_wrapper<std::reference_wrapper<T>> {
184 using type = T&;
185};
186
187// For use in make_tuple, decays a type and unwraps a reference_wrapper.
188template <typename T>
189struct unwrap_decay {
190 using type = typename unwrap_reference_wrapper<typename std::decay<T>::type>::type;
191};
192
196template <typename Tuple>
198
199template <typename... Types>
200struct tuple_size<TupleImpl<sizeof...(Types), Types...>> : std::integral_constant<size_t, sizeof...(Types)> {};
201
209template <size_t Idx, typename... Types>
210constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename tuple_get_impl<Idx, Types...>::ReturnType& get(
211 const TupleImpl<sizeof...(Types), Types...>& tuple) {
212 return tuple_get_impl<Idx, Types...>::run(tuple);
213}
214
215template <size_t Idx, typename... Types>
216constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename tuple_get_impl<Idx, Types...>::ReturnType& get(
217 TupleImpl<sizeof...(Types), Types...>& tuple) {
218 return tuple_get_impl<Idx, Types...>::run(tuple);
219}
220
226template <typename... Tuples, typename EnableIf = std::enable_if_t<
227 internal::reduce_all<is_tuple<typename std::decay<Tuples>::type>::value...>::value>>
228constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
229 typename tuple_cat_impl<sizeof...(Tuples), typename std::decay<Tuples>::type...>::ReturnType
230 tuple_cat(Tuples&&... tuples) {
231 return tuple_cat_impl<sizeof...(Tuples), typename std::decay<Tuples>::type...>::run(std::forward<Tuples>(tuples)...);
232}
233
237template <typename... Args, typename ReturnType = TupleImpl<sizeof...(Args), Args&...>>
238constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ReturnType tie(Args&... args) noexcept {
239 return ReturnType{args...};
240}
241
245template <typename... Args, typename ReturnType = TupleImpl<sizeof...(Args), typename unwrap_decay<Args>::type...>>
246constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ReturnType make_tuple(Args&&... args) {
247 return ReturnType{std::forward<Args>(args)...};
248}
249
253template <typename... Args>
254constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TupleImpl<sizeof...(Args), Args...> forward_as_tuple(Args&&... args) {
255 return TupleImpl<sizeof...(Args), Args...>(std::forward<Args>(args)...);
256}
257
261template <typename... Types>
262using tuple = TupleImpl<sizeof...(Types), Types...>;
263
264} // namespace tuple_impl
265} // namespace internal
266} // namespace Eigen
267
268#endif // EIGEN_TUPLE_GPU
Namespace containing all symbols from the Eigen library.
Definition B01_Experimental.dox:1
std::enable_if_t< std::is_base_of< DenseBase< std::decay_t< DerivedA > >, std::decay_t< DerivedA > >::value &&std::is_base_of< DenseBase< std::decay_t< DerivedB > >, std::decay_t< DerivedB > >::value, void > swap(DerivedA &&a, DerivedB &&b)
Definition DenseBase.h:667