Embedded Template Library 1.0
Loading...
Searching...
No Matches
tuple.h
1/******************************************************************************
2The MIT License(MIT)
3
4Embedded Template Library.
5https://github.com/ETLCPP/etl
6https://www.etlcpp.com
7
8Copyright(c) 2014 John Wellbelove
9
10Permission is hereby granted, free of charge, to any person obtaining a copy
11of this software and associated documentation files(the "Software"), to deal
12in the Software without restriction, including without limitation the rights
13to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
14copies of the Software, and to permit persons to whom the Software is
15furnished to do so, subject to the following conditions :
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
23AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26SOFTWARE.
27******************************************************************************/
28
29#ifndef ETL_TUPLE_INCLUDED
30#define ETL_TUPLE_INCLUDED
31
32#include "platform.h"
33
34#if ETL_USING_CPP11
35
36 #if ETL_USING_STL
37 #include <tuple>
38 #include <utility>
39 #endif
40
41 #include "functional.h"
42 #include "nth_type.h"
43 #include "type_list.h"
44 #include "type_traits.h"
45 #include "utility.h"
46
48 #include "private/tuple_size.h"
49
50namespace etl
51{
52 //***************************************************************************
55 //***************************************************************************
56 template <typename... TTypes>
57 class tuple;
58
59 //***************************************************************************
62 //***************************************************************************
63 template <typename T>
64 struct is_tuple : etl::false_type
65 {
66 };
67
68 //***************************************************************************
71 //***************************************************************************
72 template <typename... TTypes>
73 struct is_tuple<etl::tuple<TTypes...>> : etl::true_type
74 {
75 };
76
77 namespace private_tuple
78 {
79 //***************************************************************************
81 //***************************************************************************
82 template <typename T, typename TTuple>
83 struct tuple_type_base;
84
85 // Specialisation for an empty tuple
86 template <typename T>
87 struct tuple_type_base<T, tuple<>>
88 {
89 using type = void;
90 };
91
92 // Recursive definition of the type.
93 template <typename T, typename THead, typename... TTail>
94 struct tuple_type_base<T, tuple<THead, TTail...>>
95 {
96 using type = etl::conditional_t<etl::is_same<T, THead>::value, tuple<THead, TTail...>, typename tuple_type_base<T, tuple<TTail...>>::type>;
97 };
98
99 // Get the base of a tuple type whose head type is T.
100 template <typename T, typename TTuple>
101 using tuple_type_base_t = typename tuple_type_base<T, TTuple>::type;
102
103 //***************************************************************************
109 //***************************************************************************
110 struct ignore_t
111 {
112 template <typename T>
113 ETL_CONSTEXPR ignore_t operator=(T&&) const ETL_NOEXCEPT
114 {
115 return *this;
116 }
117 };
118 } // namespace private_tuple
119
120 //***************************************************************************
122 //***************************************************************************
123 template <>
124 class tuple<>
125 {
126 public:
127
128 using value_type = void;
129 using this_type = tuple<>;
130 using base_type = void;
131 using type_list = etl::type_list<>;
132 using index_sequence_type = etl::make_index_sequence<0>;
133
134 //*********************************
135 // No-op copy_assignment for the base case
136 //*********************************
137 ETL_CONSTEXPR14 void copy_assignment(const this_type& /*other*/)
138 {
139 }
140
141 //*********************************
142 // No-op forward_assignment for the base case
143 //*********************************
144 ETL_CONSTEXPR14 void forward_assignment(this_type&& /*other*/)
145 {
146 }
147
148 //*********************************
149 // No-op swap for the base case
150 //*********************************
151 ETL_CONSTEXPR14 void swap(this_type& /*other*/)
152 {
153 }
154
155 //*********************************
156 // Returns the size of the base case.
157 // Always zero.
158 //*********************************
159 ETL_NODISCARD ETL_CONSTEXPR static size_t size()
160 {
161 return 0U;
162 }
163 };
164
165 //***************************************************************************
167 //***************************************************************************
168 template <typename THead, typename... TTail>
169 class tuple<THead, TTail...> : public tuple<TTail...>
170 {
171 private:
172
173 //*********************************
176 //*********************************
177 template <typename... UTypes>
178 static constexpr size_t number_of_types()
179 {
180 return sizeof...(UTypes);
181 }
182
183 public:
184
185 //*********************************
187 //*********************************
188 template <typename... UTypes>
189 friend class tuple;
190
191 template <size_t Index, typename... TTypes>
192 ETL_CONSTEXPR14 friend etl::tuple_element_t<Index, etl::tuple<TTypes...>>& get(tuple<TTypes...>&);
193
194 template <size_t Index, typename... TTypes>
195 ETL_CONSTEXPR14 friend etl::tuple_element_t<Index, etl::tuple<TTypes...>>&& get(tuple<TTypes...>&&);
196
197 template <size_t Index, typename... TTypes>
198 ETL_CONSTEXPR14 friend const etl::tuple_element_t<Index, etl::tuple<TTypes...>>& get(const tuple<TTypes...>&);
199
200 template <size_t Index, typename... TTypes>
201 ETL_CONSTEXPR14 friend const etl::tuple_element_t<Index, etl::tuple<TTypes...>>&& get(const tuple<TTypes...>&&);
202
203 template <typename T, typename... TTypes>
204 ETL_CONSTEXPR14 friend T& get(tuple<TTypes...>&);
205
206 template <typename T, typename... TTypes>
207 ETL_CONSTEXPR14 friend T&& get(tuple<TTypes...>&&);
208
209 template <typename T, typename... TTypes>
210 ETL_CONSTEXPR14 friend const T& get(const tuple<TTypes...>&);
211
212 template <typename T, typename... TTypes>
213 ETL_CONSTEXPR14 friend const T&& get(const tuple<TTypes...>&&);
214
215 //*********************************
217 //*********************************
218 using value_type = THead;
219 using this_type = tuple<THead, TTail...>;
220 using base_type = tuple<TTail...>;
221 using type_list = etl::type_list<THead, TTail...>;
222 using index_sequence_type = etl::make_index_sequence< number_of_types< THead, TTail...>()>;
224
225 //*********************************
227 //*********************************
228 ETL_CONSTEXPR14 tuple()
229 : value()
230 {
231 }
232
233 //*********************************
235 //*********************************
236 ETL_CONSTEXPR14 tuple(const tuple<THead, TTail...>& other) = default;
237
238 //*********************************
240 //*********************************
241 ETL_CONSTEXPR14 tuple(tuple<THead, TTail...>&& other) = default;
242
243 //*********************************
245 //*********************************
246 ETL_CONSTEXPR14 tuple& operator=(const tuple<THead, TTail...>& other) = default;
247
248 //*********************************
250 //*********************************
251 ETL_CONSTEXPR14 tuple& operator=(tuple<THead, TTail...>&& other) = default;
252
253 //*********************************
256 //*********************************
257 template < typename UHead, typename... UTail,
258 etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>())
259 && (number_of_types<THead, TTail...>() >= 1U) && etl::is_convertible<UHead, THead>::value,
260 int> = 0>
261 ETL_CONSTEXPR14 tuple(tuple<UHead, UTail...>& other)
262 : base_type(other.get_base())
263 , value(other.get_value())
264 {
265 }
266
267 //*********************************
270 //*********************************
271 template < typename UHead, typename... UTail,
272 etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>())
273 && (number_of_types<THead, TTail...>() >= 1U) && !etl::is_convertible<UHead, THead>::value,
274 int> = 0>
275 ETL_CONSTEXPR14 explicit tuple(tuple<UHead, UTail...>& other)
276 : base_type(other.get_base())
277 , value(other.get_value())
278 {
279 }
280
281 //*********************************
284 //*********************************
285 template < typename UHead, typename... UTail,
286 etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>())
287 && (number_of_types<THead, TTail...>() >= 1U) && etl::is_convertible<UHead, THead>::value,
288 int> = 0>
289 ETL_CONSTEXPR14 tuple(const tuple<UHead, UTail...>& other)
290 : base_type(other.get_base())
291 , value(other.get_value())
292 {
293 }
294
295 //*********************************
298 //*********************************
299 template < typename UHead, typename... UTail,
300 etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>())
301 && (number_of_types<THead, TTail...>() >= 1U) && !etl::is_convertible<UHead, THead>::value,
302 int> = 0>
303 ETL_CONSTEXPR14 explicit tuple(const tuple<UHead, UTail...>& other)
304 : base_type(other.get_base())
305 , value(other.get_value())
306 {
307 }
308
309 //*********************************
312 //*********************************
313 template < typename UHead, typename... UTail,
314 etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>())
315 && (number_of_types<THead, TTail...>() >= 1U) && etl::is_convertible<UHead, THead>::value,
316 int> = 0>
317 ETL_CONSTEXPR14 tuple(tuple<UHead, UTail...>&& other)
318 : base_type(etl::forward<tuple<UTail...>>(other.get_base()))
319 , value(etl::forward<UHead>(other.get_value()))
320 {
321 }
322
323 //*********************************
326 //*********************************
327 template < typename UHead, typename... UTail,
328 etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>())
329 && (number_of_types<THead, TTail...>() >= 1U) && !etl::is_convertible<UHead, THead>::value,
330 int> = 0>
331 ETL_CONSTEXPR14 explicit tuple(tuple<UHead, UTail...>&& other)
332 : base_type(etl::forward<tuple<UTail...>>(other.get_base()))
333 , value(etl::forward<UHead>(other.get_value()))
334 {
335 }
336
337 //*********************************
340 //*********************************
341 template < typename UHead, typename... UTail,
342 etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>())
343 && (number_of_types<THead, TTail...>() >= 1U) && etl::is_convertible<UHead, THead>::value,
344 int> = 0>
345 ETL_CONSTEXPR14 tuple(const tuple<UHead, UTail...>&& other)
346 : base_type(other.get_base())
347 , value(other.get_value())
348 {
349 }
350
351 //*********************************
354 //*********************************
355 template < typename UHead, typename... UTail,
356 etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>())
357 && (number_of_types<THead, TTail...>() >= 1U) && !etl::is_convertible<UHead, THead>::value,
358 int> = 0>
359 ETL_CONSTEXPR14 explicit tuple(const tuple<UHead, UTail...>&& other)
360 : base_type(other.get_base())
361 , value(other.get_value())
362 {
363 }
364
365 //*********************************
367 //*********************************
368 ETL_CONSTEXPR14 tuple(const THead& head, const TTail&... tail)
369 : base_type(tail...)
370 , value(head)
371 {
372 }
373
374 //*********************************
377 //*********************************
378 template <
379 typename UHead, typename... UTail,
380 etl::enable_if_t< !is_tuple<etl::remove_reference_t<UHead>>::value && (number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>())
381 && (number_of_types<THead, TTail...>() >= 1U) && etl::is_convertible<UHead, THead>::value,
382 int> = 0>
383 ETL_CONSTEXPR14 tuple(UHead&& head, UTail&&... tail) ETL_NOEXCEPT
384 : base_type(etl::forward<UTail>(tail)...)
385 , value(etl::forward<UHead>(head))
386 {
387 }
388
389 //*********************************
392 //*********************************
393 template <
394 typename UHead, typename... UTail,
395 etl::enable_if_t<!is_tuple<etl::remove_reference_t<UHead>>::value && (number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>())
396 && (number_of_types<THead, TTail...>() >= 1U) && !etl::is_convertible<UHead, THead>::value,
397 int> = 0>
398 ETL_CONSTEXPR14 explicit tuple(UHead&& head, UTail&&... tail) ETL_NOEXCEPT
399 : base_type(etl::forward<UTail>(tail)...)
400 , value(etl::forward<UHead>(head))
401 {
402 }
403
404 //*********************************
407 //*********************************
408 template <typename U1, typename U2,
409 etl::enable_if_t<number_of_types<THead, TTail...>() == 2U && etl::is_convertible<U1, THead>::value
410 && etl::is_convertible< U2, typename base_type::value_type>::value,
411 int> = 0>
412 ETL_CONSTEXPR14 tuple(ETL_OR_STD::pair<U1, U2>& p) ETL_NOEXCEPT
413 : base_type(p.second)
414 , value(p.first)
415 {
416 }
417
418 //*********************************
421 //*********************************
422 template < typename U1, typename U2,
423 etl::enable_if_t<number_of_types<THead, TTail...>() == 2U
424 && (!etl::is_convertible<U1, THead>::value || !etl::is_convertible< U2, typename base_type::value_type>::value),
425 int> = 0>
426 ETL_CONSTEXPR14 explicit tuple(ETL_OR_STD::pair<U1, U2>& p) ETL_NOEXCEPT
427 : base_type(p.second)
428 , value(p.first)
429 {
430 }
431
432 //*********************************
435 //*********************************
436 template <typename U1, typename U2,
437 etl::enable_if_t<number_of_types<THead, TTail...>() == 2U && etl::is_convertible<U1, THead>::value
438 && etl::is_convertible< U2, typename base_type::value_type>::value,
439 int> = 0>
440 ETL_CONSTEXPR14 tuple(const ETL_OR_STD::pair<U1, U2>& p) ETL_NOEXCEPT
441 : base_type(p.second)
442 , value(p.first)
443 {
444 }
445
446 //*********************************
449 //*********************************
450 template < typename U1, typename U2,
451 etl::enable_if_t<number_of_types<THead, TTail...>() == 2U
452 && (!etl::is_convertible<U1, THead>::value || !etl::is_convertible< U2, typename base_type::value_type>::value),
453 int> = 0>
454 ETL_CONSTEXPR14 explicit tuple(const ETL_OR_STD::pair<U1, U2>& p) ETL_NOEXCEPT
455 : base_type(p.second)
456 , value(p.first)
457 {
458 }
459
460 //*********************************
463 //*********************************
464 template <typename U1, typename U2,
465 etl::enable_if_t<number_of_types<THead, TTail...>() == 2U && etl::is_convertible<U1, THead>::value
466 && etl::is_convertible< U2, typename base_type::value_type>::value,
467 int> = 0>
468 ETL_CONSTEXPR14 tuple(ETL_OR_STD::pair<U1, U2>&& p) ETL_NOEXCEPT
469 : base_type(etl::forward<U2>(p.second))
470 , value(etl::forward<U1>(p.first))
471 {
472 }
473
474 //*********************************
477 //*********************************
478 template < typename U1, typename U2,
479 etl::enable_if_t<number_of_types<THead, TTail...>() == 2U
480 && (!etl::is_convertible<U1, THead>::value || !etl::is_convertible< U2, typename base_type::value_type>::value),
481 int> = 0>
482 ETL_CONSTEXPR14 explicit tuple(ETL_OR_STD::pair<U1, U2>&& p) ETL_NOEXCEPT
483 : base_type(etl::forward<U2>(p.second))
484 , value(etl::forward<U1>(p.first))
485 {
486 }
487
488 //*********************************
491 //*********************************
492 template <typename U1, typename U2,
493 etl::enable_if_t<number_of_types<THead, TTail...>() == 2U && etl::is_convertible<U1, THead>::value
494 && etl::is_convertible< U2, typename base_type::value_type>::value,
495 int> = 0>
496 ETL_CONSTEXPR14 tuple(const ETL_OR_STD::pair<U1, U2>&& p) ETL_NOEXCEPT
497 : base_type(etl::forward<const U2>(p.second))
498 , value(etl::forward<const U1>(p.first))
499 {
500 }
501
502 //*********************************
505 //*********************************
506 template < typename U1, typename U2,
507 etl::enable_if_t<number_of_types<THead, TTail...>() == 2U
508 && (!etl::is_convertible<U1, THead>::value || !etl::is_convertible< U2, typename base_type::value_type>::value),
509 int> = 0>
510 ETL_CONSTEXPR14 explicit tuple(const ETL_OR_STD::pair<U1, U2>&& p) ETL_NOEXCEPT
511 : base_type(etl::forward<const U2>(p.second))
512 , value(etl::forward<const U1>(p.first))
513 {
514 }
515
516 //*********************************
518 //*********************************
519 template < typename UHead, typename... UTail,
520 etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>()), int> = 0>
521 ETL_CONSTEXPR14 tuple& operator=(const tuple<UHead, UTail...>& other)
522 {
523 copy_assignment(other);
524
525 return *this;
526 }
527
528 //*********************************
530 //*********************************
531 template < typename UHead, typename... UTail,
532 etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>()), int> = 0>
533 ETL_CONSTEXPR14 tuple& operator=(tuple<UHead, UTail...>&& other)
534 {
535 forward_assignment(etl::forward<tuple<UHead, UTail...>>(other));
536
537 return *this;
538 }
539
540 //*********************************
542 //*********************************
543 template <typename U1, typename U2, size_t NTypes = number_of_types<THead, TTail...>(), etl::enable_if_t<NTypes == 2U, int> = 0>
544 ETL_CONSTEXPR14 tuple& operator=(ETL_OR_STD::pair<U1, U2>& p)
545 {
546 get_value() = p.first;
547 get_base().get_value() = p.second;
548
549 return *this;
550 }
551
552 //*********************************
554 //*********************************
555 template <typename U1, typename U2, size_t NTypes = number_of_types<THead, TTail...>(), etl::enable_if_t<NTypes == 2U, int> = 0>
556 ETL_CONSTEXPR14 tuple& operator=(const ETL_OR_STD::pair<U1, U2>& p)
557 {
558 get_value() = p.first;
559 get_base().get_value() = p.second;
560
561 return *this;
562 }
563
564 //*********************************
566 //*********************************
567 template <typename U1, typename U2, size_t NTypes = number_of_types<THead, TTail...>(), etl::enable_if_t<NTypes == 2U, int> = 0>
568 ETL_CONSTEXPR14 tuple& operator=(ETL_OR_STD::pair<U1, U2>&& p)
569 {
570 get_value() = etl::forward<U1>(p.first);
571 get_base().get_value() = etl::forward<U2>(p.second);
572
573 return *this;
574 }
575
576 //*********************************
578 //*********************************
579 template <typename U1, typename U2, size_t NTypes = number_of_types<THead, TTail...>(), etl::enable_if_t<NTypes == 2U, int> = 0>
580 ETL_CONSTEXPR14 tuple& operator=(const ETL_OR_STD::pair<U1, U2>&& p)
581 {
582 get_value() = etl::forward<const U1>(p.first);
583 get_base().get_value() = etl::forward<const U2>(p.second);
584
585 return *this;
586 }
587
588 //*********************************
590 //*********************************
591 ETL_CONSTEXPR14 void swap(this_type& other)
592 {
593 using ETL_OR_STD::swap;
594
595 // Swap the head
596 swap(get_value(), other.get_value());
597
598 auto& this_base = get_base();
599 auto& other_base = other.get_base();
600
601 // Recursively swap the tail by calling the base class's swap
602 // implementation.
603 this_base.swap(other_base);
604 }
605
606 //*********************************
608 //*********************************
609 ETL_NODISCARD
610 constexpr static size_t size()
611 {
612 return number_of_types<THead, TTail...>();
613 }
614
615 protected:
616
617 //*********************************
619 //*********************************
620 ETL_NODISCARD ETL_CONSTEXPR14 THead& get_value()
621 {
622 return value;
623 }
624
625 //*********************************
627 //*********************************
628 ETL_CONSTEXPR const THead& get_value() const
629 {
630 return value;
631 }
632
633 //*********************************
635 //*********************************
636 ETL_NODISCARD ETL_CONSTEXPR14 base_type& get_base()
637 {
638 return static_cast<base_type&>(*this);
639 }
640
641 //*********************************
643 //*********************************
644 ETL_NODISCARD ETL_CONSTEXPR14 const base_type& get_base() const
645 {
646 return static_cast<const base_type&>(*this);
647 }
648
649 //*********************************
651 //*********************************
652 template <typename UHead, typename... UTail>
653 ETL_CONSTEXPR14 void copy_assignment(const tuple<UHead, UTail...>& other)
654 {
655 // Assign the head
656 this->value = other.get_value();
657
658 // Get the base classes
659 auto& this_base = get_base();
660 const auto& other_base = other.get_base();
661
662 // Recursively assign the tail by calling the base class's assignment
663 // implementation
664 this_base.copy_assignment(other_base);
665 }
666
667 //*********************************
669 //*********************************
670 template <typename UHead, typename... UTail>
671 ETL_CONSTEXPR14 void forward_assignment(tuple<UHead, UTail...>&& other)
672 {
673 // Assign the head
674 this->value = etl::forward<UHead>(other.get_value());
675
676 auto& this_base = get_base();
677 auto&& other_base = other.get_base();
678
679 // Recursively assign the tail by calling the base class's move assignment
680 // implementation
681 this_base.forward_assignment(etl::forward<tuple<UTail...>>(other_base));
682 }
683
684 private:
685
686 THead value;
687 };
688
689 #if ETL_USING_CPP17
690 //***************************************************************************
692 //***************************************************************************
693 template <typename... TArgs>
694 tuple(TArgs... args) -> tuple<TArgs...>;
695
696 //***************************************************************************
698 //***************************************************************************
699 template <typename T1, typename T2>
700 tuple(ETL_OR_STD::pair<T1, T2>) -> tuple<T1, T2>;
701 #endif
702
703 //***************************************************************************
705 //***************************************************************************
706 template <size_t Index, typename... TTypes>
707 struct tuple_element<Index, etl::tuple<TTypes...>>
708 {
709 using type = etl::nth_type_t<Index, TTypes...>;
710 };
711
712 //***************************************************************************
714 //***************************************************************************
715 template <typename... TTypes>
716 struct tuple_size<etl::tuple<TTypes...>> : etl::integral_constant<size_t, sizeof...(TTypes)>
717 {
718 };
719
720 //***************************************************************************
722 //***************************************************************************
723 template <typename... Types>
724 struct common_type<etl::tuple<Types...>>
725 {
726 using type = etl::common_type_t<Types...>;
727 };
728
729 //***************************************************************************
733 //***************************************************************************
734 template <size_t Index, typename... TTypes>
735 ETL_NODISCARD ETL_CONSTEXPR14 etl::tuple_element_t<Index, etl::tuple<TTypes...>>& get(tuple<TTypes...>& t)
736 {
737 ETL_STATIC_ASSERT(Index < sizeof...(TTypes), "etl::get<Index> - Index out of range");
738
739 // Get the type at this index.
740 using tuple_type = etl::nth_base_t<Index, tuple<TTypes...>>&;
741
742 // Cast the tuple to the selected type and get the value.
743 return static_cast<tuple_type>(t).get_value();
744 }
745
746 //***************************************************************************
750 //***************************************************************************
751 template <size_t Index, typename... TTypes>
752 ETL_NODISCARD ETL_CONSTEXPR14 const etl::tuple_element_t<Index, etl::tuple<TTypes...>>& get(const tuple<TTypes...>& t)
753 {
754 ETL_STATIC_ASSERT(Index < sizeof...(TTypes), "etl::get<Index> - Index out of range");
755
756 // Get the type at this index.
757 using tuple_type = const etl::nth_base_t<Index, tuple<TTypes...>>&;
758
759 // Cast the tuple to the selected type and get the value.
760 return static_cast<tuple_type>(t).get_value();
761 }
762
763 //***************************************************************************
767 //***************************************************************************
768 template <size_t Index, typename... TTypes>
769 ETL_NODISCARD ETL_CONSTEXPR14 etl::tuple_element_t<Index, etl::tuple<TTypes...>>&& get(tuple<TTypes...>&& t)
770 {
771 ETL_STATIC_ASSERT(Index < sizeof...(TTypes), "etl::get<Index> - Index out of range");
772
773 // Get the type at this index.
774 using tuple_type = etl::nth_base_t<Index, tuple<TTypes...>>&&;
775 using element_type = etl::tuple_element_t<Index, etl::tuple<TTypes...>>;
776
777 // Forward the element. A reference member must not be turned into an
778 // rvalue, so cast to element_type&& (which collapses to a reference type
779 // when element_type is itself a reference).
780 return static_cast<element_type&&>(static_cast<tuple_type>(t).get_value());
781 }
782
783 //***************************************************************************
787 //***************************************************************************
788 template <size_t Index, typename... TTypes>
789 ETL_NODISCARD ETL_CONSTEXPR14 const etl::tuple_element_t<Index, etl::tuple<TTypes...>>&& get(const tuple<TTypes...>&& t)
790 {
791 ETL_STATIC_ASSERT(Index < sizeof...(TTypes), "etl::get<Index> - Index out of range");
792
793 // Get the type at this index.
794 using tuple_type = const etl::nth_base_t<Index, etl::tuple<TTypes...>>&&;
795 using element_type = etl::tuple_element_t<Index, etl::tuple<TTypes...>>;
796
797 // Forward the element. A reference member must not be turned into an
798 // rvalue, so cast to const element_type&& (which collapses to a reference
799 // type when element_type is itself a reference).
800 return static_cast<const element_type&&>(static_cast<tuple_type>(t).get_value());
801 }
802
803 //***************************************************************************
807 //***************************************************************************
808 template <typename T, typename... TTypes>
809 ETL_NODISCARD ETL_CONSTEXPR14 T& get(tuple<TTypes...>& t)
810 {
811 ETL_STATIC_ASSERT(!(etl::has_duplicates_of<T, TTypes...>::value), "etl::get<Type> - Tuple contains duplicate instances of T");
812 ETL_STATIC_ASSERT((etl::is_one_of<T, TTypes...>::value), "etl::get<Type> - Tuple does not contain the specified type");
813
814 // Get the tuple base type that contains a T
815 using tuple_type = etl::private_tuple::tuple_type_base_t<T, tuple<TTypes...>>&;
816
817 // Cast the tuple to the selected type and get the value.
818 return static_cast<tuple_type>(t).get_value();
819 }
820
821 //***************************************************************************
825 //***************************************************************************
826 template <typename T, typename... TTypes>
827 ETL_NODISCARD ETL_CONSTEXPR14 const T& get(const tuple<TTypes...>& t)
828 {
829 ETL_STATIC_ASSERT(!(etl::has_duplicates_of<T, TTypes...>::value), "etl::get<Type> - Tuple contains duplicate instances of T");
830 ETL_STATIC_ASSERT((etl::is_one_of<T, TTypes...>::value), "etl::get<Type> - Tuple does not contain the specified type");
831
832 // Get the tuple base type that contains a T
833 using tuple_type = const etl::private_tuple::tuple_type_base_t<T, tuple<TTypes...>>&;
834
835 // Cast the tuple to the selected type and get the value.
836 return static_cast<tuple_type>(t).get_value();
837 }
838
839 //***************************************************************************
843 //***************************************************************************
844 template <typename T, typename... TTypes>
845 ETL_NODISCARD ETL_CONSTEXPR14 T&& get(tuple<TTypes...>&& t)
846 {
847 ETL_STATIC_ASSERT(!(etl::has_duplicates_of<T, TTypes...>::value), "etl::get<Type> - Tuple contains duplicate instances of T");
848 ETL_STATIC_ASSERT((etl::is_one_of<T, TTypes...>::value), "etl::get<Type> - Tuple does not contain the specified type");
849
850 // Get the tuple base type that contains a T
851 using tuple_type = etl::private_tuple::tuple_type_base_t<T, tuple<TTypes...>>&&;
852
853 // Forward the element. A reference type T must not be turned into an
854 // rvalue, so cast to T&& (which collapses to a reference when T is a
855 // reference type).
856 return static_cast<T&&>(static_cast<tuple_type>(t).get_value());
857 }
858
859 //***************************************************************************
863 //***************************************************************************
864 template <typename T, typename... TTypes>
865 ETL_NODISCARD ETL_CONSTEXPR14 const T&& get(const tuple<TTypes...>&& t)
866 {
867 ETL_STATIC_ASSERT(!(etl::has_duplicates_of<T, TTypes...>::value), "etl::get<Type> - Tuple contains duplicate instances of T");
868 ETL_STATIC_ASSERT((etl::is_one_of<T, TTypes...>::value), "etl::get<Type> - Tuple does not contain the specified type");
869
870 // Get the tuple base type that contains a T
871 using tuple_type = const etl::private_tuple::tuple_type_base_t<T, tuple<TTypes...>>&&;
872
873 // Forward the element. A reference type T must not be turned into an
874 // rvalue, so cast to const T&& (which collapses to a reference when T is a
875 // reference type).
876 return static_cast<const T&&>(static_cast<tuple_type>(t).get_value());
877 }
878
879 #if ETL_USING_CPP17
880 inline constexpr private_tuple::ignore_t ignore;
881 #else
882 static constexpr private_tuple::ignore_t ignore;
883 #endif
884
885 //***************************************************************************
887 //***************************************************************************
888 template <typename... TTypes>
889 ETL_CONSTEXPR etl::tuple<TTypes&...> tie(TTypes&... args)
890 {
891 return {args...};
892 }
893
894 //***************************************************************************
895 // Creates a tuple from the provided arguments.
896 //***************************************************************************
897 template <typename... TTypes>
898 ETL_NODISCARD ETL_CONSTEXPR14 etl::tuple<etl::unwrap_ref_decay_t<TTypes>...> make_tuple(TTypes&&... args)
899 {
900 return etl::tuple<unwrap_ref_decay_t<TTypes>...>(etl::forward<TTypes>(args)...);
901 }
902
903 //***************************************************************************
907 //***************************************************************************
908 template <typename TTuple, size_t... Indices>
909 ETL_NODISCARD ETL_CONSTEXPR14 auto select_from_tuple(TTuple&& tuple,
910 etl::index_sequence<Indices...>) -> etl::tuple<etl::tuple_element_t<Indices, etl::decay_t<TTuple>>...>
911 {
912 ETL_STATIC_ASSERT(sizeof...(Indices) <= etl::tuple_size<etl::decay_t<TTuple>>::value, "Number of indices is greater than the tuple size");
913
914 return etl::make_tuple(etl::forward<etl::tuple_element_t<Indices, etl::decay_t<TTuple>>>(etl::get<Indices>(etl::forward<TTuple>(tuple)))...);
915 }
916
917 //***************************************************************************
921 //***************************************************************************
922 template <size_t... Indices, typename TTuple>
923 ETL_NODISCARD ETL_CONSTEXPR14 auto select_from_tuple(TTuple&& tuple) -> etl::tuple<etl::tuple_element_t<Indices, etl::decay_t<TTuple>>...>
924 {
925 return select_from_tuple(etl::forward<TTuple>(tuple), etl::index_sequence<Indices...>{});
926 }
927
928 //***************************************************************************
930 //***************************************************************************
931 template <typename... TTypes>
932 ETL_NODISCARD ETL_CONSTEXPR14 etl::tuple<TTypes&&...> forward_as_tuple(TTypes&&... args)
933 {
934 return tuple<TTypes&&...>(etl::forward<TTypes>(args)...);
935 }
936
937 namespace private_tuple
938 {
939 //**********************************
940 // Helper to concatenate two tuples
941 //**********************************
942 template <typename Tuple1, typename Tuple2, size_t... Index1, size_t... Index2>
943 ETL_CONSTEXPR14 auto tuple_cat_impl(Tuple1&& t1, etl::index_sequence<Index1...>, Tuple2&& t2, etl::index_sequence<Index2...>)
944 -> etl::tuple<etl::tuple_element_t<Index1, etl::decay_t<Tuple1>>..., etl::tuple_element_t<Index2, etl::decay_t<Tuple2>>...>
945 {
946 return etl::tuple<etl::tuple_element_t<Index1, etl::decay_t<Tuple1>>..., etl::tuple_element_t<Index2, etl::decay_t<Tuple2>>...>(
947 etl::get<Index1>(etl::forward<Tuple1>(t1))..., etl::get<Index2>(etl::forward<Tuple2>(t2))...);
948 }
949 } // namespace private_tuple
950
951 //***************************************************************************
953 //***************************************************************************
954 template <typename Tuple>
955 ETL_NODISCARD ETL_CONSTEXPR14 auto tuple_cat(Tuple&& t) -> Tuple
956 {
957 return etl::forward<Tuple>(t);
958 }
959
960 //***************************************************************************
962 //***************************************************************************
963 template <typename Tuple1, typename Tuple2, typename... Tuples>
964 ETL_NODISCARD ETL_CONSTEXPR14 auto tuple_cat(Tuple1&& t1, Tuple2&& t2, Tuples&&... ts)
965 -> decltype(tuple_cat(private_tuple::tuple_cat_impl(etl::forward<Tuple1>(t1),
966 etl::make_index_sequence< etl::tuple_size<etl::decay_t<Tuple1>>::value>{},
967 etl::forward<Tuple2>(t2),
968 etl::make_index_sequence< etl::tuple_size<etl::decay_t<Tuple2>>::value>{}),
969 etl::forward<Tuples>(ts)...))
970 {
971 return tuple_cat(
972 private_tuple::tuple_cat_impl(etl::forward<Tuple1>(t1), etl::make_index_sequence< etl::tuple_size<etl::decay_t<Tuple1>>::value>{},
973 etl::forward<Tuple2>(t2), etl::make_index_sequence< etl::tuple_size<etl::decay_t<Tuple2>>::value>{}),
974 etl::forward<Tuples>(ts)...);
975 }
976
977 #if ETL_USING_STL
978 //***************************************************************************
979 // Tuple conversion functions.
980 // From ETL to STL
981 //***************************************************************************
982 namespace private_tuple
983 {
985 template <typename TEtl_Tuple, size_t... Indices>
986 ETL_NODISCARD ETL_CONSTEXPR14 auto to_std_impl(const TEtl_Tuple& etl_tuple,
987 etl::index_sequence<Indices...>) -> std::tuple<typename etl::tuple_element_t<Indices, TEtl_Tuple>...>
988 {
989 return std::tuple<etl::tuple_element_t<Indices, TEtl_Tuple>...>(etl::get<Indices>(etl_tuple)...);
990 }
991
993 template <typename TEtl_Tuple, size_t... Indices>
994 ETL_NODISCARD ETL_CONSTEXPR14 auto to_std_impl(TEtl_Tuple&& etl_tuple, etl::index_sequence<Indices...>) -> std::tuple<etl::tuple_element_t<Indices, TEtl_Tuple>...>
995 {
996 return std::tuple<etl::tuple_element_t<Indices, TEtl_Tuple>...>(etl::move(etl::get<Indices>(etl_tuple))...);
997 }
998 } // namespace private_tuple
999
1000 //***************************************************************************
1002 //***************************************************************************
1003 template <typename... TTypes>
1004 ETL_NODISCARD ETL_CONSTEXPR14 auto to_std(const etl::tuple<TTypes...>& etl_tuple) -> std::tuple<etl::decay_t<TTypes>...>
1005 {
1006 return private_tuple::to_std_impl(etl_tuple, etl::make_index_sequence_for<TTypes...>());
1007 }
1008
1009 //***************************************************************************
1011 //***************************************************************************
1012 template <typename... TTypes>
1013 ETL_NODISCARD ETL_CONSTEXPR14 auto to_std(etl::tuple<TTypes...>&& etl_tuple) -> std::tuple<etl::decay_t<TTypes>...>
1014 {
1015 return private_tuple::to_std_impl(etl::move(etl_tuple), etl::make_index_sequence_for<TTypes...>());
1016 }
1017
1018 //***************************************************************************
1021 //***************************************************************************
1022 namespace private_tuple
1023 {
1025 template <typename TStd_Tuple, size_t... Indices>
1026 ETL_NODISCARD ETL_CONSTEXPR14 auto to_etl_impl(const TStd_Tuple& std_tuple,
1027 etl::index_sequence<Indices...>) -> etl::tuple<typename std::tuple_element<Indices, TStd_Tuple>::type...>
1028 {
1029 return etl::tuple< typename std::tuple_element<Indices, TStd_Tuple>::type...>(std::get<Indices>(std_tuple)...);
1030 }
1031
1033 template <typename TStd_Tuple, size_t... Indices>
1034 ETL_NODISCARD ETL_CONSTEXPR14 auto to_etl_impl(TStd_Tuple&& std_tuple,
1035 etl::index_sequence<Indices...>) -> etl::tuple<typename std::tuple_element<Indices, TStd_Tuple>::type...>
1036 {
1037 return etl::tuple< typename std::tuple_element<Indices, TStd_Tuple>::type...>(std::move(std::get<Indices>(std_tuple))...);
1038 }
1039 } // namespace private_tuple
1040
1041 //***************************************************************************
1043 //***************************************************************************
1044 template <typename... TTypes>
1045 ETL_NODISCARD ETL_CONSTEXPR14 auto to_etl(const std::tuple<TTypes...>& std_tuple) -> etl::tuple<etl::decay_t<TTypes>...>
1046 {
1047 return private_tuple::to_etl_impl(std_tuple, etl::make_index_sequence_for<TTypes...>());
1048 }
1049
1050 //***************************************************************************
1052 //***************************************************************************
1053 template <typename... TTypes>
1054 ETL_NODISCARD ETL_CONSTEXPR14 auto to_etl(std::tuple<TTypes...>&& std_tuple) -> etl::tuple<etl::decay_t<TTypes>...>
1055 {
1056 return private_tuple::to_etl_impl(etl::move(std_tuple), etl::make_index_sequence_for<TTypes...>());
1057 }
1058 #endif
1059
1060 namespace private_tuple
1061 {
1062 //***************************************************************************
1064 //***************************************************************************
1065 // When there are no indices left to compare.
1066 template <typename TTuple1, typename TTuple2>
1067 ETL_NODISCARD ETL_CONSTEXPR14 bool tuple_equality(const TTuple1& /*lhs*/, const TTuple2& /*rhs*/, etl::index_sequence<>)
1068 {
1069 return true;
1070 }
1071
1072 // Recursive case: compare the current element and recurse.
1073 template <typename TTuple1, typename TTuple2, size_t Index, size_t... Indices>
1074 ETL_NODISCARD ETL_CONSTEXPR14 bool tuple_equality(const TTuple1& lhs, const TTuple2& rhs, etl::index_sequence<Index, Indices...>)
1075 {
1076 return etl::get<Index>(lhs) == etl::get<Index>(rhs) && tuple_equality(lhs, rhs, etl::index_sequence<Indices...>{});
1077 }
1078
1079 //***************************************************************************
1081 //***************************************************************************
1082 // When there are no indices left to compare.
1083 template <typename TTuple1, typename TTuple2>
1084 ETL_NODISCARD ETL_CONSTEXPR14 bool tuple_less_than(const TTuple1& /*lhs*/, const TTuple2& /*rhs*/, etl::index_sequence<>)
1085 {
1086 return false;
1087 }
1088
1089 // Recursively compare the current element and the rest.
1090 template <typename TTuple1, typename TTuple2, size_t Index, size_t... Indices>
1091 ETL_NODISCARD ETL_CONSTEXPR14 bool tuple_less_than(const TTuple1& lhs, const TTuple2& rhs, etl::index_sequence<Index, Indices...>)
1092 {
1093 if (get<Index>(lhs) < get<Index>(rhs))
1094 {
1095 return true;
1096 }
1097
1098 if (get<Index>(rhs) < get<Index>(lhs))
1099 {
1100 return false;
1101 }
1102
1103 return tuple_less_than(lhs, rhs, etl::index_sequence<Indices...>{});
1104 }
1105 } // namespace private_tuple
1106
1107 //***************************************************************************
1109 //***************************************************************************
1110 template <typename... TTypes, typename... UTypes>
1111 ETL_NODISCARD ETL_CONSTEXPR14 bool operator==(const etl::tuple<TTypes...>& lhs, const etl::tuple<UTypes...>& rhs)
1112 {
1113 ETL_STATIC_ASSERT(sizeof...(TTypes) == sizeof...(UTypes), "Cannot compare tuples of different sizes");
1114
1115 // Compare each element of the tuples.
1116 return private_tuple::tuple_equality(lhs, rhs, etl::make_index_sequence<etl::tuple<TTypes...>::size()>{});
1117 }
1118
1119 //***************************************************************************
1121 //***************************************************************************
1122 template <typename... TTypes, typename... UTypes>
1123 ETL_NODISCARD ETL_CONSTEXPR14 bool operator!=(const etl::tuple<TTypes...>& lhs, const etl::tuple<UTypes...>& rhs)
1124 {
1125 return !(lhs == rhs);
1126 }
1127
1128 //***************************************************************************
1130 //***************************************************************************
1131 template <typename... TTypes, typename... UTypes>
1132 ETL_NODISCARD ETL_CONSTEXPR14 bool operator<(const etl::tuple<TTypes...>& lhs, const etl::tuple<UTypes...>& rhs)
1133 {
1134 ETL_STATIC_ASSERT(sizeof...(TTypes) == sizeof...(UTypes), "Cannot compare tuples of different sizes");
1135
1136 // Compare the elements.
1137 return private_tuple::tuple_less_than(lhs, rhs, etl::make_index_sequence<etl::tuple<TTypes...>::size()>{});
1138 }
1139
1140 //***************************************************************************
1142 //***************************************************************************
1143 template <typename... TTypes, typename... UTypes>
1144 ETL_NODISCARD ETL_CONSTEXPR14 bool operator<=(const etl::tuple<TTypes...>& lhs, const etl::tuple<UTypes...>& rhs)
1145 {
1146 return !(rhs < lhs);
1147 }
1148
1149 //***************************************************************************
1151 //***************************************************************************
1152 template <typename... TTypes, typename... UTypes>
1153 ETL_NODISCARD ETL_CONSTEXPR14 bool operator>(const etl::tuple<TTypes...>& lhs, const etl::tuple<UTypes...>& rhs)
1154 {
1155 return (rhs < lhs);
1156 }
1157
1158 //***************************************************************************
1160 //***************************************************************************
1161 template <typename... TTypes, typename... UTypes>
1162 ETL_NODISCARD ETL_CONSTEXPR14 bool operator>=(const etl::tuple<TTypes...>& lhs, const etl::tuple<UTypes...>& rhs)
1163 {
1164 return !(lhs < rhs);
1165 }
1166
1167 //***************************************************************************
1169 //***************************************************************************
1170 template <typename... TTypes>
1171 ETL_CONSTEXPR14 void swap(etl::tuple<TTypes...>& lhs, etl::tuple<TTypes...>& rhs)
1172 {
1173 lhs.swap(rhs);
1174 }
1175
1176 //***************************************************************************
1178 template <typename TList>
1179 struct tuple_from_type_list;
1180
1181 template <typename... TTypes>
1182 struct tuple_from_type_list<etl::type_list<TTypes...>>
1183 {
1184 using type = etl::tuple<TTypes...>;
1185 };
1186
1187 template <typename TTypeList>
1188 using tuple_from_type_list_t = typename tuple_from_type_list<TTypeList>::type;
1189} // namespace etl
1190
1191namespace std
1192{
1193 // libc++ already declares std::tuple_size / std::tuple_element in its inline
1194 // namespace (std::__1), so re-declaring them here would make the name
1195 // ambiguous. Detect libc++ via _LIBCPP_VERSION and skip the forward
1196 // declarations in that case, even when not using the STL.
1197 #if ETL_NOT_USING_STL && !defined(_LIBCPP_VERSION) \
1198 && !((defined(ETL_DEVELOPMENT_OS_APPLE) || (ETL_COMPILER_FULL_VERSION >= 190000) && (ETL_COMPILER_FULL_VERSION < 210000)) \
1199 && defined(ETL_COMPILER_CLANG))
1200 template <typename T>
1201 struct tuple_size;
1202
1203 template <size_t Index, typename TType>
1204 struct tuple_element;
1205 #endif
1206
1207 //***************************************************************************
1209 //***************************************************************************
1210 template <typename... Types>
1211 struct tuple_size<etl::tuple<Types...>> : etl::integral_constant<size_t, sizeof...(Types)>
1212 {
1213 };
1214
1215 //***************************************************************************
1218 //***************************************************************************
1219 template <size_t Index, typename... Types>
1220 struct tuple_element<Index, etl::tuple<Types...>>
1221 {
1222 using type = etl::nth_type_t<Index, Types...>;
1223 };
1224} // namespace std
1225
1226#endif
1227#endif
void swap(etl::array_view< T > &lhs, etl::array_view< T > &rhs) ETL_NOEXCEPT
Swaps the values.
Definition array_view.h:692
Definition absolute.h:40
ETL_CONSTEXPR14 void swap(etl::typed_storage_ext< T > &lhs, etl::typed_storage_ext< T > &rhs) ETL_NOEXCEPT
Swap two etl::typed_storage_ext.
Definition alignment.h:856
ETL_CONSTEXPR14 bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1078
bool operator>(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1130
integral_constant< bool, false > false_type
integral_constant specialisations
Definition type_traits.h:80
bool operator>=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1144
ETL_CONSTEXPR14 bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1090
ETL_CONSTEXPR TContainer::size_type size(const TContainer &container)
Definition iterator.h:1434
T & get(array< T, Size > &a)
Definition array.h:1158
bool operator<(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1103
bool operator<=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1117
Definition tuple_size.h:38