SPH
Tuple.h
Go to the documentation of this file.
1 #pragma once
2 
7 
8 #include "common/Traits.h"
9 
11 
12 namespace Detail {
13 template <std::size_t TIndex, typename TValue>
14 class TupleValue {
15  TValue value;
16 
17 public:
18  constexpr TupleValue() = default;
19 
20  template <typename T>
21  INLINE constexpr TupleValue(T&& value)
22  : value(std::forward<T>(value)) {}
23 
24  template <typename T>
25  INLINE constexpr TupleValue& operator=(T&& t) {
26  value = std::forward<T>(t);
27  return *this;
28  }
29 
30  using ReturnType = std::conditional_t<std::is_rvalue_reference<TValue>::value, TValue&&, TValue&>;
31 
33  INLINE constexpr ReturnType get() {
34  return static_cast<ReturnType>(value);
35  }
36 
40  INLINE constexpr const TValue& get() const {
41  return value;
42  }
43 
46  INLINE constexpr TValue&& forward() {
47  return std::forward<TValue>(value);
48  }
49 };
50 
51 template <typename TSequence, typename... TArgs>
52 class TupleImpl;
53 
54 template <std::size_t... TIndices, typename... TArgs>
55 class TupleImpl<std::index_sequence<TIndices...>, TArgs...> : TupleValue<TIndices, TArgs>... {
56 private:
57  static_assert(sizeof...(TIndices) == sizeof...(TArgs), "Internal error in tuple");
58 
59  template <std::size_t TIndex>
60  using Value = TupleValue<TIndex, SelectType<TIndex, TArgs...>>;
61 
62 public:
63  constexpr TupleImpl() = default;
64 
65  template <typename... Ts,
66  typename = std::enable_if_t<AllTrue<std::is_constructible<TArgs, Ts>::value...>::value>>
67  INLINE constexpr TupleImpl(Ts&&... args)
68  : TupleValue<TIndices, TArgs>(std::forward<Ts>(args))... {}
69 
70  template <typename... Ts>
71  INLINE constexpr TupleImpl(const TupleImpl<Ts...>& other)
72  : TupleValue<TIndices, TArgs>(other.template get<TIndices>())... {}
73 
74  template <typename... Ts>
75  INLINE constexpr TupleImpl(TupleImpl<Ts...>&& other)
76  : TupleValue<TIndices, TArgs>(other.template forward<TIndices>())... {}
77 
78  template <std::size_t TIndex>
79  INLINE constexpr decltype(auto) get() {
80  return Value<TIndex>::get();
81  }
82 
83  template <std::size_t TIndex>
84  INLINE constexpr decltype(auto) get() const {
85  return Value<TIndex>::get();
86  }
87 
88  template <std::size_t TIndex>
89  INLINE constexpr decltype(auto) forward() {
90  return Value<TIndex>::forward();
91  }
92 
93 protected:
94  template <typename... Ts, std::size_t TIndex, std::size_t... TIdxs>
95  INLINE void copyAssign(const TupleImpl<Ts...>& other, std::index_sequence<TIndex, TIdxs...>) {
96  this->get<TIndex>() = other.template get<TIndex>();
97  copyAssign(other, std::index_sequence<TIdxs...>());
98  }
99 
100  template <typename... Ts>
101  INLINE void copyAssign(const TupleImpl<Ts...>& UNUSED(other), std::index_sequence<>) {}
102 
103  template <typename... Ts, std::size_t TIndex, std::size_t... TIdxs>
104  INLINE void copyAssign(TupleImpl<Ts...>& other, std::index_sequence<TIndex, TIdxs...>) {
105  this->get<TIndex>() = other.template get<TIndex>();
106  copyAssign(other, std::index_sequence<TIdxs...>());
107  }
108 
109  template <typename... Ts>
110  INLINE void copyAssign(TupleImpl<Ts...>& UNUSED(other), std::index_sequence<>) {}
111 
112  template <typename... Ts, std::size_t TIndex, std::size_t... TIdxs>
113  INLINE void moveAssign(TupleImpl<Ts...>&& other, std::index_sequence<TIndex, TIdxs...>) {
114  this->get<TIndex>() = other.template forward<TIndex>();
115  moveAssign(std::move(other), std::index_sequence<TIdxs...>());
116  }
117 
118  template <typename... Ts>
119  INLINE void moveAssign(const TupleImpl<Ts...>& UNUSED(other), std::index_sequence<>) {}
120 
121  template <typename... Ts, std::size_t TIndex, std::size_t... TIdxs>
122  INLINE bool isEqual(const TupleImpl<Ts...>& other, std::index_sequence<TIndex, TIdxs...>) const {
123  return this->get<TIndex>() == other.template get<TIndex>() &&
124  isEqual(other, std::index_sequence<TIdxs...>());
125  }
126 
127  template <typename... Ts>
128  INLINE bool isEqual(const TupleImpl<Ts...>& UNUSED(other), std::index_sequence<>) const {
129  return true;
130  }
131 };
132 } // namespace Detail
133 
135 template <typename T>
136 struct IsTuple {
137  static constexpr bool value = false;
138 };
139 
140 
145 template <typename... TArgs>
146 class Tuple : public Detail::TupleImpl<std::index_sequence_for<TArgs...>, TArgs...> {
147 private:
148  using Sequence = std::index_sequence_for<TArgs...>;
149  using Impl = Detail::TupleImpl<Sequence, TArgs...>;
150 
151 public:
152  INLINE constexpr Tuple() = default;
153 
154  template <typename... Ts,
155  typename = std::enable_if_t<AllTrue<std::is_constructible<TArgs, Ts>::value...>::value>>
156  INLINE constexpr Tuple(Ts&&... args)
157  : Impl(std::forward<Ts>(args)...) {}
158 
159  INLINE constexpr Tuple(const Tuple& other)
160  : Impl(other) {}
161 
162  INLINE constexpr Tuple(Tuple&& other)
163  : Impl(std::move(other)) {}
164 
165  template <typename... Ts>
166  INLINE constexpr Tuple(const Tuple<Ts...>& other)
167  : Impl(other) {}
168 
169  template <typename... Ts>
170  INLINE constexpr Tuple(Tuple<Ts...>&& other)
171  : Impl(std::move(other)) {}
172 
176  this->copyAssign(other, Sequence());
177  return *this;
178  }
179 
181  INLINE Tuple& operator=(const Tuple& other) {
182  this->copyAssign(other, Sequence());
183  return *this;
184  }
185 
189  this->copyAssign(std::move(other), Sequence());
190  return *this;
191  }
192 
194  template <typename... Ts>
196  static_assert(sizeof...(Ts) == sizeof...(TArgs), "Cannot assign tuples of different sizes");
197  this->copyAssign(other, Sequence());
198  return *this;
199  }
200 
202  template <typename... Ts>
204  static_assert(sizeof...(Ts) == sizeof...(TArgs), "Cannot assign tuples of different sizes");
205  this->copyAssign(other, Sequence());
206  return *this;
207  }
208 
210  template <typename... Ts>
212  static_assert(sizeof...(Ts) == sizeof...(TArgs), "Cannot assign tuples of different sizes");
213  this->moveAssign(std::move(other), Sequence());
214  return *this;
215  }
216 
220  template <std::size_t TIndex>
221  INLINE constexpr decltype(auto) get() & {
222  static_assert(unsigned(TIndex) < sizeof...(TArgs), "Index out of bounds.");
223  return Impl::template get<TIndex>();
224  }
225 
227  template <std::size_t TIndex>
228  INLINE constexpr decltype(auto) get() const & {
229  static_assert(unsigned(TIndex) < sizeof...(TArgs), "Index out of bounds.");
230  return Impl::template get<TIndex>();
231  }
232 
236  template <std::size_t TIndex>
237  INLINE constexpr decltype(auto) get() && {
238  static_assert(unsigned(TIndex) < sizeof...(TArgs), "Index out of bounds.");
239  return Impl::template forward<TIndex>();
240  }
241 
244  template <typename Type>
245  INLINE constexpr decltype(auto) get() & {
246  constexpr std::size_t index = getTypeIndex<Type, TArgs...>;
247  static_assert(index != -1, "Type not stored in tuple");
248  return Impl::template get<index>();
249  }
250 
252  template <typename Type>
253  INLINE constexpr decltype(auto) get() const & {
254  constexpr std::size_t index = getTypeIndex<Type, TArgs...>;
255  static_assert(index != -1, "Type not stored in tuple");
256  return Impl::template get<index>();
257  }
258 
260  template <typename Type>
261  INLINE constexpr decltype(auto) get() && {
262  constexpr std::size_t index = getTypeIndex<Type, TArgs...>;
263  static_assert(index != -1, "Type not stored in tuple");
264  return Impl::template forward<index>();
265  }
266 
268  INLINE static constexpr std::size_t size() noexcept {
269  return sizeof...(TArgs);
270  }
271 
273  INLINE constexpr bool operator==(const Tuple& other) const {
274  return Impl::isEqual(other, Sequence());
275  }
276 
277  INLINE constexpr bool operator!=(const Tuple& other) const {
278  return !Impl::isEqual(other, Sequence());
279  }
280 };
281 
282 template <typename... TArgs>
283 struct IsTuple<Tuple<TArgs...>&> {
284  static constexpr bool value = true;
285 };
286 template <typename... TArgs>
287 struct IsTuple<const Tuple<TArgs...>&> {
288  static constexpr bool value = true;
289 };
290 template <typename... TArgs>
291 struct IsTuple<Tuple<TArgs...>&&> {
292  static constexpr bool value = true;
293 };
294 
295 
297 template <typename... TArgs>
298 INLINE auto makeTuple(TArgs&&... args) {
299  return Tuple<std::decay_t<TArgs>...>(std::forward<TArgs>(args)...);
300 }
301 
303 template <typename... TArgs>
304 INLINE Tuple<TArgs&...> tieToTuple(TArgs&... args) {
305  return Tuple<TArgs&...>(args...);
306 }
307 
311 template <typename... TArgs>
312 INLINE Tuple<TArgs&&...> forwardAsTuple(TArgs&&... args) {
313  return Tuple<TArgs&&...>(std::forward<TArgs>(args)...);
314 }
315 
317 const struct Ignore {
318  template <typename T>
319  const Ignore& operator=(T&&) const {
320  return *this;
321  }
323 
324 namespace Detail {
325 template <typename... Ts1, typename... Ts2, std::size_t... TIdxs>
326 INLINE constexpr Tuple<Ts1..., Ts2...> appendImpl(const Tuple<Ts1...>& tuple,
327  std::index_sequence<TIdxs...>,
328  Ts2&&... values) {
329  return Tuple<Ts1..., Ts2...>(tuple.template get<TIdxs>()..., std::forward<Ts2>(values)...);
330 }
331 
332 template <typename... Ts1, typename... Ts2, std::size_t... TIdxs>
333 INLINE constexpr Tuple<Ts1..., Ts2...> appendImpl(Tuple<Ts1...>&& tuple,
334  std::index_sequence<TIdxs...>,
335  Ts2&&... values) {
336  return Tuple<Ts1..., Ts2...>(std::move(tuple).template get<TIdxs>()..., std::forward<Ts2>(values)...);
337 }
338 
339 template <typename... Ts1, typename... Ts2, std::size_t... TIdxs1, std::size_t... TIdxs2>
340 INLINE constexpr Tuple<Ts1..., Ts2...> appendImpl(const Tuple<Ts1...>& t1,
341  const Tuple<Ts2...>& t2,
342  std::index_sequence<TIdxs1...>,
343  std::index_sequence<TIdxs2...>) {
344  return Tuple<Ts1..., Ts2...>(t1.template get<TIdxs1>()..., t2.template get<TIdxs2>()...);
345 }
346 } // namespace Detail
347 
350 template <typename... Ts1, typename... Ts2>
351 INLINE constexpr Tuple<Ts1..., Ts2...> append(const Tuple<Ts1...>& tuple, Ts2&&... values) {
352  return Detail::appendImpl(tuple, std::index_sequence_for<Ts1...>(), std::forward<Ts2>(values)...);
353 }
354 
356 template <typename... Ts1, typename... Ts2>
357 INLINE constexpr Tuple<Ts1..., Ts2...> append(Tuple<Ts1...>&& tuple, Ts2&&... values) {
358  return Detail::appendImpl(
359  std::move(tuple), std::index_sequence_for<Ts1...>(), std::forward<Ts2>(values)...);
360 }
361 
363 template <typename... Ts1, typename... Ts2>
364 INLINE constexpr Tuple<Ts1..., Ts2...> append(const Tuple<Ts1...>& t1, const Tuple<Ts2...>& t2) {
365  return Detail::appendImpl(t1, t2, std::index_sequence_for<Ts1...>(), std::index_sequence_for<Ts2...>());
366 }
367 
370 template <typename TTuple, typename Type>
372  static constexpr bool value = false;
373 };
374 template <typename... TArgs, typename Type>
375 struct TupleContains<Tuple<TArgs...>, Type> {
376  static constexpr bool value = (getTypeIndex<Type, TArgs...> != -1);
377 };
378 
380 template <typename TTuple, std::size_t TIndex>
382 template <typename... TArgs, std::size_t TIndex>
383 struct TupleElementType<Tuple<TArgs...>, TIndex> {
384  using Type = SelectType<TIndex, TArgs...>;
385 };
386 template <typename... TArgs, std::size_t TIndex>
387 struct TupleElementType<Tuple<TArgs...>&, TIndex> {
388  using Type = SelectType<TIndex, TArgs...>;
389 };
390 template <typename... TArgs, std::size_t TIndex>
391 struct TupleElementType<const Tuple<TArgs...>&, TIndex> {
392  using Type = SelectType<TIndex, TArgs...>;
393 };
394 template <typename... TArgs, std::size_t TIndex>
395 struct TupleElementType<Tuple<TArgs...>&&, TIndex> {
396  using Type = SelectType<TIndex, TArgs...>;
397 };
398 
399 template <typename TTuple, std::size_t TIndex>
401 
402 
403 namespace Detail {
404 template <typename TFunctor, typename TTuple>
406  TTuple&& tuple;
407  TFunctor&& functor;
408 
409  template <std::size_t TIndex>
410  INLINE void visit() {
411  functor(tuple.template get<TIndex>());
412  }
413 };
414 
415 template <typename TFunctor, typename TTuple, template <class> class TTrait>
417  TTuple&& tuple;
418  TFunctor&& functor;
419 
420  template <std::size_t TIndex>
421  INLINE std::enable_if_t<TTrait<TupleElement<TTuple, TIndex>>::value> visit() {
422  functor(tuple.template get<TIndex>());
423  }
424 
425  template <std::size_t TIndex>
426  INLINE std::enable_if_t<!TTrait<TupleElement<TTuple, TIndex>>::value> visit() {}
427 };
428 } // namespace Detail
429 
432 template <typename TFunctor, typename... TArgs>
433 INLINE void forEach(Tuple<TArgs...>& tuple, TFunctor&& functor) {
434  Detail::ForEachVisitor<TFunctor, decltype(tuple)> visitor{ tuple, std::forward<TFunctor>(functor) };
435  staticFor<0, sizeof...(TArgs) - 1>(std::move(visitor));
436 }
437 
439 template <typename TFunctor, typename... TArgs>
440 INLINE void forEach(const Tuple<TArgs...>& tuple, TFunctor&& functor) {
441  Detail::ForEachVisitor<TFunctor, decltype(tuple)> visitor{ tuple, std::forward<TFunctor>(functor) };
442  staticFor<0, sizeof...(TArgs) - 1>(std::move(visitor));
443 }
444 
446 template <typename TFunctor, typename... TArgs>
447 INLINE void forEach(Tuple<TArgs...>&& tuple, TFunctor&& functor) {
448  Detail::ForEachVisitor<TFunctor, decltype(tuple)> visitor{ std::move(tuple),
449  std::forward<TFunctor>(functor) };
450  staticFor<0, sizeof...(TArgs) - 1>(std::move(visitor));
451 }
452 
454 template <template <class T> class TTrait, typename TFunctor, typename... TArgs>
455 INLINE void forEachIf(Tuple<TArgs...>& tuple, TFunctor&& functor) {
456  Detail::ForEachIfVisitor<TFunctor, decltype(tuple), TTrait> visitor{ tuple,
457  std::forward<TFunctor>(functor) };
458  staticFor<0, sizeof...(TArgs) - 1>(std::move(visitor));
459 }
460 
463 template <template <class T> class TTrait, typename TFunctor, typename... TArgs>
464 INLINE void forEachIf(const Tuple<TArgs...>& tuple, TFunctor&& functor) {
465  Detail::ForEachIfVisitor<TFunctor, decltype(tuple), TTrait> visitor{ tuple,
466  std::forward<TFunctor>(functor) };
467  staticFor<0, sizeof...(TArgs) - 1>(std::move(visitor));
468 }
469 
470 
471 namespace Detail {
472 template <typename TFunctor, typename TTuple, std::size_t... TIndices>
473 INLINE decltype(auto) applyImpl(TTuple&& tuple, TFunctor&& functor, std::index_sequence<TIndices...>) {
474  return functor(std::forward<TTuple>(tuple).template get<TIndices>()...);
475 }
476 } // namespace Detail
477 
479 template <typename TFunctor, typename... TArgs>
480 INLINE decltype(auto) apply(Tuple<TArgs...>& tuple, TFunctor&& functor) {
481  return Detail::applyImpl(tuple, std::forward<TFunctor>(functor), std::index_sequence_for<TArgs...>());
482 }
483 
485 template <typename TFunctor, typename... TArgs>
486 INLINE decltype(auto) apply(const Tuple<TArgs...>& tuple, TFunctor&& functor) {
487  return Detail::applyImpl(tuple, std::forward<TFunctor>(functor), std::index_sequence_for<TArgs...>());
488 }
489 
491 template <typename TFunctor, typename... TArgs>
492 INLINE decltype(auto) apply(Tuple<TArgs...>&& tuple, TFunctor&& functor) {
493  return Detail::applyImpl(
494  std::move(tuple), std::forward<TFunctor>(functor), std::index_sequence_for<TArgs...>());
495 }
496 
497 
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
#define INLINE
Macros for conditional compilation based on selected compiler.
Definition: Object.h:31
INLINE void staticFor(TVisitor &&visitor)
Definition: Object.h:123
#define UNUSED(x)
Definition: Object.h:37
#define NAMESPACE_SPH_END
Definition: Object.h:12
Few non-standard type traits.
typename TypeSelector< n, TArgs... >::Type SelectType
Definition: Traits.h:27
constexpr int getTypeIndex
Definition: Traits.h:41
INLINE Tuple< TArgs &... > tieToTuple(TArgs &... args)
Creates a tuple of l-value references. Use IGNORE placeholder to omit one or more parameters.
Definition: Tuple.h:304
INLINE void forEachIf(Tuple< TArgs... > &tuple, TFunctor &&functor)
Iterates over elements of the tuple and executes a functor if given type traits has value == true.
Definition: Tuple.h:455
constexpr INLINE Tuple< Ts1..., Ts2... > append(const Tuple< Ts1... > &tuple, Ts2 &&... values)
Definition: Tuple.h:351
decltype(auto) INLINE apply(Tuple< TArgs... > &tuple, TFunctor &&functor)
Expands arguments stored in tuple into parameter pack of a functor.
Definition: Tuple.h:480
const struct Ignore IGNORE
INLINE void forEach(Tuple< TArgs... > &tuple, TFunctor &&functor)
Definition: Tuple.h:433
INLINE Tuple< TArgs &&... > forwardAsTuple(TArgs &&... args)
Definition: Tuple.h:312
INLINE auto makeTuple(TArgs &&... args)
Creates a tuple from a pack of values, utilizing type deduction.
Definition: Tuple.h:298
typename TupleElementType< TTuple, TIndex >::Type TupleElement
Definition: Tuple.h:400
INLINE bool isEqual(const TupleImpl< Ts... > &UNUSED(other), std::index_sequence<>) const
Definition: Tuple.h:128
constexpr INLINE TupleImpl(const TupleImpl< Ts... > &other)
Definition: Tuple.h:71
INLINE void copyAssign(TupleImpl< Ts... > &UNUSED(other), std::index_sequence<>)
Definition: Tuple.h:110
INLINE void moveAssign(const TupleImpl< Ts... > &UNUSED(other), std::index_sequence<>)
Definition: Tuple.h:119
constexpr INLINE TupleImpl(TupleImpl< Ts... > &&other)
Definition: Tuple.h:75
INLINE bool isEqual(const TupleImpl< Ts... > &other, std::index_sequence< TIndex, TIdxs... >) const
Definition: Tuple.h:122
INLINE void copyAssign(const TupleImpl< Ts... > &UNUSED(other), std::index_sequence<>)
Definition: Tuple.h:101
INLINE void copyAssign(TupleImpl< Ts... > &other, std::index_sequence< TIndex, TIdxs... >)
Definition: Tuple.h:104
INLINE void moveAssign(TupleImpl< Ts... > &&other, std::index_sequence< TIndex, TIdxs... >)
Definition: Tuple.h:113
INLINE void copyAssign(const TupleImpl< Ts... > &other, std::index_sequence< TIndex, TIdxs... >)
Definition: Tuple.h:95
constexpr TupleValue()=default
constexpr INLINE TupleValue(T &&value)
Definition: Tuple.h:21
constexpr INLINE ReturnType get()
Return r-value reference if TValue is an r-value reference, otherwise returns l-value reference.
Definition: Tuple.h:33
std::conditional_t< std::is_rvalue_reference< TValue >::value, TValue &&, TValue & > ReturnType
Definition: Tuple.h:30
constexpr INLINE const TValue & get() const
Definition: Tuple.h:40
constexpr INLINE TValue && forward()
Definition: Tuple.h:46
constexpr INLINE TupleValue & operator=(T &&t)
Definition: Tuple.h:25
Heterogeneous container capable of storing a fixed number of values.
Definition: Tuple.h:146
INLINE Tuple & operator=(Tuple< Ts... > &other)
Assigns tuple of generally different types. Same rules as above apply.
Definition: Tuple.h:195
static constexpr INLINE std::size_t size() noexcept
Returns the number of elements in tuple.
Definition: Tuple.h:268
constexpr INLINE Tuple(Tuple &&other)
Definition: Tuple.h:162
constexpr INLINE Tuple()=default
constexpr INLINE bool operator!=(const Tuple &other) const
Definition: Tuple.h:277
constexpr decltype(auto) INLINE get() &
Definition: Tuple.h:221
constexpr INLINE Tuple(Tuple< Ts... > &&other)
Definition: Tuple.h:170
constexpr INLINE Tuple(Ts &&... args)
Definition: Tuple.h:156
INLINE Tuple & operator=(Tuple< Ts... > &&other)
Assigns tuple of generally different types. Same rules as above apply.
Definition: Tuple.h:211
INLINE Tuple & operator=(const Tuple &other)
Assign conts l-value reference of tuple. All values are copied.
Definition: Tuple.h:181
INLINE Tuple & operator=(const Tuple< Ts... > &other)
Assigns tuple of generally different types. Same rules as above apply.
Definition: Tuple.h:203
INLINE Tuple & operator=(Tuple &&other)
Definition: Tuple.h:188
constexpr INLINE Tuple(const Tuple &other)
Definition: Tuple.h:159
constexpr INLINE Tuple(const Tuple< Ts... > &other)
Definition: Tuple.h:166
constexpr INLINE bool operator==(const Tuple &other) const
Definition: Tuple.h:273
INLINE Tuple & operator=(Tuple &other)
Definition: Tuple.h:175
decltype(auto) INLINE applyImpl(TTuple &&tuple, TFunctor &&functor, std::index_sequence< TIndices... >)
Definition: Tuple.h:473
constexpr INLINE Tuple< Ts1..., Ts2... > appendImpl(const Tuple< Ts1... > &tuple, std::index_sequence< TIdxs... >, Ts2 &&... values)
Definition: Tuple.h:326
Overload of std::swap for Sph::Array.
Definition: Array.h:578
TFunctor && functor
Definition: Tuple.h:418
INLINE std::enable_if_t< TTrait< TupleElement< TTuple, TIndex > >::value > visit()
Definition: Tuple.h:421
INLINE std::enable_if_t<!TTrait< TupleElement< TTuple, TIndex > >::value > visit()
Definition: Tuple.h:426
TFunctor && functor
Definition: Tuple.h:407
TTuple && tuple
Definition: Tuple.h:406
INLINE void visit()
Definition: Tuple.h:410
Placeholder for unused variables in tieToTuple.
Definition: Tuple.h:317
const Ignore & operator=(T &&) const
Definition: Tuple.h:319
Useful type trait, checking whether given type is a Tuple.
Definition: Tuple.h:136
static constexpr bool value
Definition: Tuple.h:137
static constexpr bool value
Definition: Tuple.h:372
SelectType< TIndex, TArgs... > Type
Definition: Tuple.h:384
SelectType< TIndex, TArgs... > Type
Definition: Tuple.h:388
SelectType< TIndex, TArgs... > Type
Definition: Tuple.h:396
SelectType< TIndex, TArgs... > Type
Definition: Tuple.h:392
Gets type of tuple element given its index.
Definition: Tuple.h:381