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_NOT_USING_CPP11 && !defined(ETL_IN_UNIT_TEST)
35 #error NOT SUPPORTED FOR C++03 OR BELOW
36#endif
37
38#if ETL_USING_CPP11
39
40#if ETL_USING_STL
41 #include <tuple>
42#endif
43
44#include "nth_type.h"
45#include "type_traits.h"
46#include "utility.h"
47#include "functional.h"
48
50#include "private/tuple_size.h"
51
52namespace etl
53{
54 //***************************************************************************
57 //***************************************************************************
58 template <typename... TTypes>
59 class tuple;
60
61 //***************************************************************************
64 //***************************************************************************
65 template <typename T>
66 struct is_tuple : etl::false_type
67 {
68 };
69
70 //***************************************************************************
73 //***************************************************************************
74 template <typename... TTypes>
75 struct is_tuple<etl::tuple<TTypes...>> : etl::true_type
76 {
77 };
78
79 namespace private_tuple
80 {
81 //***************************************************************************
83 //***************************************************************************
84 template <typename T, typename TTuple>
85 struct tuple_type_base;
86
87 // Specialisation for an empty tuple
88 template <typename T>
89 struct tuple_type_base<T, tuple<>>
90 {
91 using type = void;
92 };
93
94 // Recursive definition of the type.
95 template <typename T, typename THead, typename... TTail>
96 struct tuple_type_base<T, tuple<THead, TTail...>>
97 {
98 using type = etl::conditional_t<etl::is_same<T, THead>::value,
99 tuple<THead, TTail...>,
100 typename tuple_type_base<T, tuple<TTail...>>::type>;
101 };
102
103 // Get the base of a tuple type whose head type is T.
104 template <typename T, typename TTuple>
105 using tuple_type_base_t = typename tuple_type_base<T, TTuple>::type;
106
107 //***************************************************************************
112 //***************************************************************************
113 struct ignore_t
114 {
115 template <typename T>
116 ETL_CONSTEXPR ignore_t operator =(T&&) const ETL_NOEXCEPT
117 {
118 return *this;
119 }
120 };
121 }
122
123 //***************************************************************************
125 //***************************************************************************
126 template<>
127 class tuple<>
128 {
129 public:
130
131 using value_type = void;
132 using this_type = tuple<>;
133 using base_type = void;
134 using index_sequence_type = etl::make_index_sequence<0>;
135
136 //*********************************
137 // No-op copy_assignment for the base case
138 //*********************************
139 ETL_CONSTEXPR14
140 void copy_assignment(const this_type& /*other*/)
141 {
142 }
143
144 //*********************************
145 // No-op forward_assignment for the base case
146 //*********************************
147 ETL_CONSTEXPR14
148 void forward_assignment(this_type&& /*other*/)
149 {
150 }
151
152 //*********************************
153 // No-op swap for the base case
154 //*********************************
155 ETL_CONSTEXPR14
156 void swap(this_type& /*other*/)
157 {
158 }
159
160 //*********************************
161 // Returns the size of the base case.
162 // Always zero.
163 //*********************************
164 ETL_NODISCARD
165 ETL_CONSTEXPR
166 static size_t size()
167 {
168 return 0U;
169 }
170 };
171
172 //***************************************************************************
174 //***************************************************************************
175 template<typename THead, typename... TTail>
176 class tuple<THead, TTail...> : public tuple<TTail...>
177 {
178 private:
179
180 //*********************************
183 //*********************************
184 template <typename... UTypes>
185 static constexpr size_t number_of_types()
186 {
187 return sizeof...(UTypes);
188 }
189
190 public:
191
192 //*********************************
194 //*********************************
195 template<typename... UTypes>
196 friend class tuple;
197
198 template <size_t Index, typename... TTypes>
199 ETL_CONSTEXPR14
200 friend etl::tuple_element_t<Index, etl::tuple<TTypes...>>& get(tuple<TTypes...>&);
201
202 template <size_t Index, typename... TTypes>
203 ETL_CONSTEXPR14
204 friend etl::tuple_element_t<Index, etl::tuple<TTypes...>>&& get(tuple<TTypes...>&&);
205
206 template <size_t Index, typename... TTypes>
207 ETL_CONSTEXPR14
208 friend const etl::tuple_element_t<Index, etl::tuple<TTypes...>>& get(const tuple<TTypes...>&);
209
210 template <size_t Index, typename... TTypes>
211 ETL_CONSTEXPR14
212 friend const etl::tuple_element_t<Index, etl::tuple<TTypes...>>&& get(const tuple<TTypes...>&&);
213
214 template <typename T, typename... TTypes>
215 ETL_CONSTEXPR14
216 friend T& get(tuple<TTypes...>&);
217
218 template <typename T, typename... TTypes>
219 ETL_CONSTEXPR14
220 friend T&& get(tuple<TTypes...>&&);
221
222 template <typename T, typename... TTypes>
223 ETL_CONSTEXPR14
224 friend const T& get(const tuple<TTypes...>&);
225
226 template <typename T, typename... TTypes>
227 ETL_CONSTEXPR14
228 friend const T&& get(const tuple<TTypes...>&&);
229
230 //*********************************
232 //*********************************
233 using value_type = THead;
234 using this_type = tuple<THead, TTail...>;
235 using base_type = tuple<TTail...>;
236 using index_sequence_type = etl::make_index_sequence<number_of_types<THead, TTail...>()>;
237
238 //*********************************
240 //*********************************
241 ETL_CONSTEXPR14
242 tuple()
243 : value()
244 {
245 }
246
247 //*********************************
249 //*********************************
250 ETL_CONSTEXPR14
251 tuple(const tuple<THead, TTail...>& other) = default;
252
253 //*********************************
255 //*********************************
256 ETL_CONSTEXPR14
257 tuple(tuple<THead, TTail...>&& other) = default;
258
259 //*********************************
261 //*********************************
262 ETL_CONSTEXPR14
263 tuple& operator =(const tuple<THead, TTail...>& other) = default;
264
265 //*********************************
267 //*********************************
268 ETL_CONSTEXPR14
269 tuple& operator =(tuple<THead, TTail...>&& other) = default;
270
271 //*********************************
274 //*********************************
275 template <typename UHead, typename... UTail, etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>()) &&
276 (number_of_types<THead, TTail...>() >= 1U) &&
277 etl::is_convertible<UHead, THead>::value, int> = 0>
278 ETL_CONSTEXPR14
279 tuple(tuple<UHead, UTail...>& other)
280 : base_type(other.get_base())
281 , value(other.get_value())
282 {
283 }
284
285 //*********************************
288 //*********************************
289 template <typename UHead, typename... UTail, etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>()) &&
290 (number_of_types<THead, TTail...>() >= 1U) &&
291 !etl::is_convertible<UHead, THead>::value, int> = 0>
292 ETL_CONSTEXPR14
293 explicit tuple(tuple<UHead, UTail...>& other)
294 : base_type(other.get_base())
295 , value(other.get_value())
296 {
297 }
298
299 //*********************************
302 //*********************************
303 template <typename UHead, typename... UTail, etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>()) &&
304 (number_of_types<THead, TTail...>() >= 1U) &&
305 etl::is_convertible<UHead, THead>::value, int> = 0>
306 ETL_CONSTEXPR14
307 tuple(const tuple<UHead, UTail...>& other)
308 : base_type(other.get_base())
309 , value(other.get_value())
310 {
311 }
312
313 //*********************************
316 //*********************************
317 template <typename UHead, typename... UTail, etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>()) &&
318 (number_of_types<THead, TTail...>() >= 1U) &&
319 !etl::is_convertible<UHead, THead>::value, int> = 0>
320 ETL_CONSTEXPR14
321 explicit tuple(const tuple<UHead, UTail...>& other)
322 : base_type(other.get_base())
323 , value(other.get_value())
324 {
325 }
326
327 //*********************************
330 //*********************************
331 template <typename UHead, typename... UTail, etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>()) &&
332 (number_of_types<THead, TTail...>() >= 1U) &&
333 etl::is_convertible<UHead, THead>::value, int> = 0>
334 ETL_CONSTEXPR14
335 tuple(tuple<UHead, UTail...>&& other)
336 : base_type(etl::forward<tuple<UTail...>>(other.get_base()))
337 , value(etl::forward<UHead>(other.get_value()))
338 {
339 }
340
341 //*********************************
344 //*********************************
345 template <typename UHead, typename... UTail, etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>()) &&
346 (number_of_types<THead, TTail...>() >= 1U) &&
347 !etl::is_convertible<UHead, THead>::value, int> = 0>
348 ETL_CONSTEXPR14
349 explicit tuple(tuple<UHead, UTail...>&& other)
350 : base_type(etl::forward<tuple<UTail...>>(other.get_base()))
351 , value(etl::forward<UHead>(other.get_value()))
352 {
353 }
354
355 //*********************************
358 //*********************************
359 template <typename UHead, typename... UTail, etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>()) &&
360 (number_of_types<THead, TTail...>() >= 1U) &&
361 etl::is_convertible<UHead, THead>::value, int> = 0>
362 ETL_CONSTEXPR14
363 tuple(const tuple<UHead, UTail...>&& other)
364 : base_type(other.get_base())
365 , value(other.get_value())
366 {
367 }
368
369 //*********************************
372 //*********************************
373 template <typename UHead, typename... UTail, etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>()) &&
374 (number_of_types<THead, TTail...>() >= 1U) &&
375 !etl::is_convertible<UHead, THead>::value, int> = 0>
376 ETL_CONSTEXPR14
377 explicit tuple(const tuple<UHead, UTail...>&& other)
378 : base_type(other.get_base())
379 , value(other.get_value())
380 {
381 }
382
383 //*********************************
385 //*********************************
386 ETL_CONSTEXPR14
387 tuple(const THead& head, const TTail&... tail)
388 : base_type(tail...)
389 , value(head)
390 {
391 }
392
393 //*********************************
396 //*********************************
397 template <typename UHead, typename... UTail, etl::enable_if_t<!is_tuple<etl::remove_reference_t<UHead>>::value &&
398 (number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>()) &&
399 (number_of_types<THead, TTail...>() >= 1U) &&
400 etl::is_convertible<UHead, THead>::value, int> = 0>
401 ETL_CONSTEXPR14
402 tuple(UHead&& head, UTail&&... tail) ETL_NOEXCEPT
403 : base_type(etl::forward<UTail>(tail)...)
404 , value(etl::forward<UHead>(head))
405 {
406 }
407
408 //*********************************
411 //*********************************
412 template <typename UHead, typename... UTail, etl::enable_if_t<!is_tuple<etl::remove_reference_t<UHead>>::value &&
413 (number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>()) &&
414 (number_of_types<THead, TTail...>() >= 1U) &&
415 !etl::is_convertible<UHead, THead>::value, int> = 0>
416 ETL_CONSTEXPR14
417 explicit tuple(UHead&& head, UTail&&... tail) ETL_NOEXCEPT
418 : base_type(etl::forward<UTail>(tail)...)
419 , value(etl::forward<UHead>(head))
420 {
421 }
422
423 //*********************************
426 //*********************************
427 template <typename U1, typename U2, etl::enable_if_t<number_of_types<THead, TTail...>() == 2U &&
428 etl ::is_convertible<U1, THead>::value &&
429 etl ::is_convertible<U2, typename base_type::value_type>::value, int> = 0>
430 ETL_CONSTEXPR14
431 tuple(ETL_OR_STD::pair<U1, U2>& p) ETL_NOEXCEPT
432 : base_type(p.second)
433 , value(p.first)
434 {
435 }
436
437 //*********************************
440 //*********************************
441 template <typename U1, typename U2, etl::enable_if_t<number_of_types<THead, TTail...>() == 2U &&
442 (!etl ::is_convertible<U1, THead>::value ||
443 !etl ::is_convertible<U2, typename base_type::value_type>::value), int> = 0>
444 ETL_CONSTEXPR14
445 explicit tuple(ETL_OR_STD::pair<U1, U2>& p) ETL_NOEXCEPT
446 : base_type(p.second)
447 , value(p.first)
448 {
449 }
450
451 //*********************************
454 //*********************************
455 template <typename U1, typename U2, etl::enable_if_t<number_of_types<THead, TTail...>() == 2U &&
456 etl ::is_convertible<U1, THead>::value &&
457 etl ::is_convertible<U2, typename base_type::value_type>::value, int> = 0>
458 ETL_CONSTEXPR14
459 tuple(const ETL_OR_STD::pair<U1, U2>& p) ETL_NOEXCEPT
460 : base_type(p.second)
461 , value(p.first)
462 {
463 }
464
465 //*********************************
468 //*********************************
469 template <typename U1, typename U2, etl::enable_if_t<number_of_types<THead, TTail...>() == 2U &&
470 (!etl ::is_convertible<U1, THead>::value ||
471 !etl ::is_convertible<U2, typename base_type::value_type>::value), int> = 0>
472 ETL_CONSTEXPR14
473 explicit tuple(const ETL_OR_STD::pair<U1, U2>& p) ETL_NOEXCEPT
474 : base_type(p.second)
475 , value(p.first)
476 {
477 }
478
479 //*********************************
482 //*********************************
483 template <typename U1, typename U2, etl::enable_if_t<number_of_types<THead, TTail...>() == 2U &&
484 etl ::is_convertible<U1, THead>::value &&
485 etl ::is_convertible<U2, typename base_type::value_type>::value, int> = 0>
486 ETL_CONSTEXPR14
487 tuple(ETL_OR_STD::pair<U1, U2>&& p) ETL_NOEXCEPT
488 : base_type(etl::forward<U2>(p.second))
489 , value(etl::forward<U1>(p.first))
490 {
491 }
492
493 //*********************************
496 //*********************************
497 template <typename U1, typename U2, etl::enable_if_t<number_of_types<THead, TTail...>() == 2U &&
498 (!etl ::is_convertible<U1, THead>::value ||
499 !etl ::is_convertible<U2, typename base_type::value_type>::value), int> = 0>
500 ETL_CONSTEXPR14
501 explicit tuple(ETL_OR_STD::pair<U1, U2>&& p) ETL_NOEXCEPT
502 : base_type(etl::forward<U2>(p.second))
503 , value(etl::forward<U1>(p.first))
504 {
505 }
506
507 //*********************************
510 //*********************************
511 template <typename U1, typename U2, etl::enable_if_t<number_of_types<THead, TTail...>() == 2U &&
512 etl ::is_convertible<U1, THead>::value &&
513 etl ::is_convertible<U2, typename base_type::value_type>::value, int> = 0>
514 ETL_CONSTEXPR14
515 tuple(const ETL_OR_STD::pair<U1, U2>&& p) ETL_NOEXCEPT
516 : base_type(etl::forward<U2>(p.second))
517 , value(etl::forward<U1>(p.first))
518 {
519 }
520
521 //*********************************
524 //*********************************
525 template <typename U1, typename U2, etl::enable_if_t<number_of_types<THead, TTail...>() == 2U &&
526 (!etl ::is_convertible<U1, THead>::value ||
527 !etl ::is_convertible<U2, typename base_type::value_type>::value), int> = 0>
528 ETL_CONSTEXPR14
529 explicit tuple(const ETL_OR_STD::pair<U1, U2>&& p) ETL_NOEXCEPT
530 : base_type(p.second)
531 , value(p.first)
532 {
533 }
534
535 //*********************************
537 //*********************************
538 template <typename UHead, typename... UTail, etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>()), int> = 0>
539 ETL_CONSTEXPR14
540 tuple& operator =(const tuple<UHead, UTail...>& other)
541 {
542 copy_assignment(other);
543
544 return *this;
545 }
546
547 //*********************************
549 //*********************************
550 template <typename UHead, typename... UTail, etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>()), int> = 0>
551 ETL_CONSTEXPR14
552 tuple& operator =(tuple<UHead, UTail...>&& other)
553 {
554 forward_assignment(etl::forward<tuple<UHead, UTail...>>(other));
555
556 return *this;
557 }
558
559 //*********************************
561 //*********************************
562 template <typename U1, typename U2, size_t NTypes = number_of_types<THead, TTail...>, etl::enable_if_t<NTypes == 2U, int> = 0>
563 ETL_CONSTEXPR14
564 tuple& operator =(pair<U1, U2>& p)
565 {
566 get_value() = p.first;
567 get_base().get_value() = p.second;
568
569 return *this;
570 }
571
572 //*********************************
574 //*********************************
575 template <typename U1, typename U2, size_t NTypes = number_of_types<THead, TTail...>, etl::enable_if_t<NTypes == 2U, int> = 0>
576 ETL_CONSTEXPR14
577 tuple& operator =(const pair<U1, U2>& p)
578 {
579 get_value() = p.first;
580 get_base().get_value() = p.second;
581
582 return *this;
583 }
584
585 //*********************************
587 //*********************************
588 template <typename U1, typename U2, size_t NTypes = number_of_types<THead, TTail...>, etl::enable_if_t<NTypes == 2U, int> = 0>
589 ETL_CONSTEXPR14
590 tuple& operator =(pair<U1, U2>&& p)
591 {
592 get_value() = etl::forward<U1>(p.first);
593 get_base().get_value() = etl::forward<U2>(p.second);
594
595 return *this;
596 }
597
598 //*********************************
600 //*********************************
601 template <typename U1, typename U2, size_t NTypes = number_of_types<THead, TTail...>, etl::enable_if_t<NTypes == 2U, int> = 0>
602 ETL_CONSTEXPR14
603 tuple& operator =(const pair<U1, U2>&& p)
604 {
605 get_value() = etl::forward<U1>(p.first);
606 get_base().get_value() = etl::forward<U2>(p.second);
607
608 return *this;
609 }
610
611 //*********************************
613 //*********************************
614 ETL_CONSTEXPR14
615 void swap(this_type& other)
616 {
617 using ETL_OR_STD::swap;
618
619 // Swap the head
620 swap(get_value(), other.get_value());
621
622 auto& this_base = get_base();
623 auto& other_base = other.get_base();
624
625 // Recursively swap the tail by calling the base class's swap implementation.
626 this_base.swap(other_base);
627 }
628
629 //*********************************
631 //*********************************
632 ETL_NODISCARD
633 constexpr
634 static size_t size()
635 {
636 return number_of_types<THead, TTail...>();
637 }
638
639 protected:
640
641 //*********************************
643 //*********************************
644 ETL_NODISCARD
645 ETL_CONSTEXPR14
646 THead& get_value()
647 {
648 return value;
649 }
650
651 //*********************************
653 //*********************************
654 ETL_CONSTEXPR
655 const THead& get_value() const
656 {
657 return value;
658 }
659
660 //*********************************
662 //*********************************
663 ETL_NODISCARD
664 ETL_CONSTEXPR14
665 base_type& get_base()
666 {
667 return static_cast<base_type&>(*this);
668 }
669
670 //*********************************
672 //*********************************
673 ETL_NODISCARD
674 ETL_CONSTEXPR14
675 const base_type& get_base() const
676 {
677 return static_cast<const base_type&>(*this);
678 }
679
680 //*********************************
682 //*********************************
683 template <typename UHead, typename... UTail>
684 ETL_CONSTEXPR14
685 void copy_assignment(const tuple<UHead, UTail...>& other)
686 {
687 // Assign the head
688 this->value = other.get_value();
689
690 // Get the base classes
691 auto& this_base = get_base();
692 const auto& other_base = other.get_base();
693
694 // Recursively assign the tail by calling the base class's assignment implementation
695 this_base.copy_assignment(other_base);
696 }
697
698 //*********************************
700 //*********************************
701 template <typename UHead, typename... UTail>
702 ETL_CONSTEXPR14
703 void forward_assignment(tuple<UHead, UTail...>&& other)
704 {
705 // Assign the head
706 this->value = etl::forward<UHead>(other.get_value());
707
708 auto& this_base = get_base();
709 auto&& other_base = other.get_base();
710
711 // Recursively assign the tail by calling the base class's move assignment implementation
712 this_base.forward_assignment(etl::forward<tuple<UTail...>>(other_base));
713 }
714
715 private:
716
717 THead value;
718 };
719
720#if ETL_USING_CPP17
721 //***************************************************************************
723 //***************************************************************************
724 template <typename... TArgs>
725 tuple(TArgs... args) -> tuple<TArgs...>;
726
727 //***************************************************************************
729 //***************************************************************************
730 template <typename T1, typename T2>
731 tuple(ETL_OR_STD::pair<T1, T2>) -> tuple<T1, T2>;
732#endif
733
734 //***************************************************************************
736 //***************************************************************************
737 template<size_t Index, typename... TTypes>
738 struct tuple_element<Index, etl::tuple<TTypes...>>
739 {
740 using type = etl::nth_type_t<Index, TTypes...>;
741 };
742
743 //***************************************************************************
745 //***************************************************************************
746 template <typename... TTypes>
747 struct tuple_size<etl::tuple<TTypes...>>
748 : etl::integral_constant<size_t, sizeof...(TTypes)>
749 {
750 };
751
752 //***************************************************************************
754 //***************************************************************************
755 template<typename... Types>
756 struct common_type<etl::tuple<Types...>>
757 {
758 using type = etl::common_type_t<Types...>;
759 };
760
761 //***************************************************************************
765 //***************************************************************************
766 template <size_t Index, typename... TTypes>
767 ETL_NODISCARD
768 ETL_CONSTEXPR14
769 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
776 // Cast the tuple to the selected type and get the value.
777 return static_cast<tuple_type>(t).get_value();
778 }
779
780 //***************************************************************************
784 //***************************************************************************
785 template <size_t Index, typename... TTypes>
786 ETL_NODISCARD
787 ETL_CONSTEXPR14
788 const etl::tuple_element_t<Index, etl::tuple<TTypes...>>& get(const tuple<TTypes...>& t)
789 {
790 ETL_STATIC_ASSERT(Index < sizeof...(TTypes), "etl::get<Index> - Index out of range");
791
792 // Get the type at this index.
793 using tuple_type = const etl::nth_base_t<Index, tuple<TTypes...>>&;
794
795 // Cast the tuple to the selected type and get the value.
796 return static_cast<tuple_type>(t).get_value();
797 }
798
799 //***************************************************************************
803 //***************************************************************************
804 template <size_t Index, typename... TTypes>
805 ETL_NODISCARD
806 ETL_CONSTEXPR14
807 etl::tuple_element_t<Index, etl::tuple<TTypes...>>&& get(tuple<TTypes...>&& t)
808 {
809 ETL_STATIC_ASSERT(Index < sizeof...(TTypes), "etl::get<Index> - Index out of range");
810
811 // Get the type at this index.
812 using tuple_type = etl::nth_base_t<Index, tuple<TTypes...>>&&;
813
814 // Cast the tuple to the selected type and get the value.
815 return etl::move(static_cast<tuple_type>(t).get_value());
816 }
817
818 //***************************************************************************
822 //***************************************************************************
823 template <size_t Index, typename... TTypes>
824 ETL_NODISCARD
825 ETL_CONSTEXPR14
826 const etl::tuple_element_t<Index, etl::tuple<TTypes...>>&& get(const tuple<TTypes...>&& t)
827 {
828 ETL_STATIC_ASSERT(Index < sizeof...(TTypes), "etl::get<Index> - Index out of range");
829
830 // Get the type at this index.
831 using tuple_type = const etl::nth_base_t<Index, etl::tuple<TTypes...>>&&;
832
833 // Cast the tuple to the selected type and get the value.
834 return etl::move(static_cast<tuple_type>(t).get_value());
835 }
836
837 //***************************************************************************
841 //***************************************************************************
842 template <typename T, typename... TTypes>
843 ETL_NODISCARD
844 ETL_CONSTEXPR14
845 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 // Cast the tuple to the selected type and get the value.
854 return static_cast<tuple_type>(t).get_value();
855 }
856
857 //***************************************************************************
861 //***************************************************************************
862 template <typename T, typename... TTypes>
863 ETL_NODISCARD
864 ETL_CONSTEXPR14
865 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 // Cast the tuple to the selected type and get the value.
874 return static_cast<tuple_type>(t).get_value();
875 }
876
877 //***************************************************************************
881 //***************************************************************************
882 template <typename T, typename... TTypes>
883 ETL_NODISCARD
884 ETL_CONSTEXPR14
885 T&& get(tuple<TTypes...>&& t)
886 {
887 ETL_STATIC_ASSERT(!(etl::has_duplicates_of<T, TTypes...>::value), "etl::get<Type> - Tuple contains duplicate instances of T");
888 ETL_STATIC_ASSERT((etl::is_one_of<T, TTypes...>::value), "etl::get<Type> - Tuple does not contain the specified type");
889
890 // Get the tuple base type that contains a T
891 using tuple_type = etl::private_tuple::tuple_type_base_t<T, tuple<TTypes...>>&&;
892
893 // Cast the tuple to the selected type and get the value.
894 return etl::move(static_cast<tuple_type>(t).get_value());
895 }
896
897 //***************************************************************************
901 //***************************************************************************
902 template <typename T, typename... TTypes>
903 ETL_NODISCARD
904 ETL_CONSTEXPR14
905 const T&& get(const tuple<TTypes...>&& t)
906 {
907 ETL_STATIC_ASSERT(!(etl::has_duplicates_of<T, TTypes...>::value), "etl::get<Type> - Tuple contains duplicate instances of T");
908 ETL_STATIC_ASSERT((etl::is_one_of<T, TTypes...>::value), "etl::get<Type> - Tuple does not contain the specified type");
909
910 // Get the tuple base type that contains a T
911 using tuple_type = const etl::private_tuple::tuple_type_base_t<T, tuple<TTypes...>>&&;
912
913 // Cast the tuple to the selected type and get the value.
914 return etl::move(static_cast<tuple_type>(t).get_value());
915 }
916
917#if ETL_USING_CPP17
918 inline constexpr private_tuple::ignore_t ignore;
919#else
920 static constexpr private_tuple::ignore_t ignore;
921#endif
922
923 //***************************************************************************
925 //***************************************************************************
926 template <typename... TTypes>
927 ETL_CONSTEXPR
928 etl::tuple<TTypes&...> tie(TTypes&... args)
929 {
930 return { args... };
931 }
932
933 //***************************************************************************
934 // Creates a tuple from the provided arguments.
935 //***************************************************************************
936 template <typename... TTypes>
937 ETL_NODISCARD
938 ETL_CONSTEXPR14
939 etl::tuple<etl::unwrap_ref_decay_t<TTypes>...> make_tuple(TTypes&&... args)
940 {
941 return etl::tuple<unwrap_ref_decay_t<TTypes>...>(etl::forward<TTypes>(args)...);
942 }
943
944 //***************************************************************************
947 //***************************************************************************
948 template <typename TTuple, size_t... Indices>
949 ETL_NODISCARD
950 ETL_CONSTEXPR14
951 auto select_from_tuple(TTuple&& tuple, etl::index_sequence<Indices...>)
952 -> etl::tuple<etl::tuple_element_t<Indices, etl::decay_t<TTuple>>...>
953 {
954 ETL_STATIC_ASSERT(sizeof...(Indices) <= etl::tuple_size<etl::decay_t<TTuple>>::value, "Number of indices is greater than the tuple size");
955
956 return etl::make_tuple(etl::forward<etl::tuple_element_t<Indices, etl::decay_t<TTuple>>>(etl::get<Indices>(etl::forward<TTuple>(tuple)))...);
957 }
958
959 //***************************************************************************
962 //***************************************************************************
963 template <size_t... Indices, typename TTuple>
964 ETL_NODISCARD
965 ETL_CONSTEXPR14
966 auto select_from_tuple(TTuple&& tuple)
967 -> etl::tuple<etl::tuple_element_t<Indices, etl::decay_t<TTuple>>...>
968 {
969 return select_from_tuple(etl::forward<TTuple>(tuple), etl::index_sequence<Indices...>{});
970 }
971
972 //***************************************************************************
974 //***************************************************************************
975 template <typename... TTypes>
976 ETL_NODISCARD
977 ETL_CONSTEXPR14
978 etl::tuple<TTypes&&...> forward_as_tuple(TTypes&&... args)
979 {
980 return tuple<TTypes&&...>(etl::forward<TTypes>(args)...);
981 }
982
983 namespace private_tuple
984 {
985 //**********************************
986 // Helper to concatenate two tuples
987 //**********************************
988 template <typename Tuple1, typename Tuple2, size_t... Index1, size_t... Index2>
989 ETL_CONSTEXPR14
990 auto tuple_cat_impl(Tuple1&& t1, etl::index_sequence<Index1...>, Tuple2&& t2, etl::index_sequence<Index2...>)
991 -> etl::tuple<etl::tuple_element_t<Index1, etl::decay_t<Tuple1>>..., etl::tuple_element_t<Index2, etl::decay_t<Tuple2>>...>
992 {
993 return etl::tuple<etl::tuple_element_t<Index1, etl::decay_t<Tuple1>>...,
994 etl::tuple_element_t<Index2, etl::decay_t<Tuple2>>...>
995 (etl::get<Index1>(etl::forward<Tuple1>(t1))..., etl::get<Index2>(etl::forward<Tuple2>(t2))...);
996 }
997 }
998
999 //***************************************************************************
1001 //***************************************************************************
1002 template <typename Tuple>
1003 ETL_NODISCARD
1004 ETL_CONSTEXPR14
1005 auto tuple_cat(Tuple&& t) -> Tuple
1006 {
1007 return etl::forward<Tuple>(t);
1008 }
1009
1010 //***************************************************************************
1012 //***************************************************************************
1013 template <typename Tuple1, typename Tuple2, typename... Tuples>
1014 ETL_NODISCARD
1015 ETL_CONSTEXPR14
1016 auto tuple_cat(Tuple1&& t1, Tuple2&& t2, Tuples&&... ts)
1017 -> decltype(private_tuple::tuple_cat_impl(etl::forward<Tuple1>(t1),
1018 etl::make_index_sequence<etl::tuple_size<etl::decay_t<Tuple1>>::value>{},
1019 etl::forward<Tuple2>(t2),
1020 etl::make_index_sequence<etl::tuple_size<etl::decay_t<Tuple2>>::value>{}))
1021 {
1022 auto concatenated = private_tuple::tuple_cat_impl(etl::forward<Tuple1>(t1),
1023 etl::make_index_sequence<etl::tuple_size<etl::decay_t<Tuple1>>::value>{},
1024 etl::forward<Tuple2>(t2),
1025 etl::make_index_sequence<etl::tuple_size<etl::decay_t<Tuple2>>::value>{});
1026
1027 return tuple_cat(etl::move(concatenated), etl::forward<Tuples>(ts)...);
1028 }
1029
1030#if ETL_USING_STL
1031 //***************************************************************************
1032 // Tuple conversion functions.
1033 // From ETL to STL
1034 //***************************************************************************
1035 namespace private_tuple
1036 {
1038 template<typename TEtl_Tuple, size_t... Indices>
1039 ETL_NODISCARD
1040 ETL_CONSTEXPR14
1041 auto to_std_impl(const TEtl_Tuple& etl_tuple, etl::index_sequence<Indices...>)
1042 -> std::tuple<typename etl::tuple_element_t<Indices, TEtl_Tuple>...>
1043 {
1044 return std::tuple<etl::tuple_element_t<Indices, TEtl_Tuple>...>(etl::get<Indices>(etl_tuple)...);
1045 }
1046
1048 template<typename TEtl_Tuple, size_t... Indices>
1049 ETL_NODISCARD
1050 ETL_CONSTEXPR14
1051 auto to_std_impl(TEtl_Tuple&& etl_tuple, etl::index_sequence<Indices...>)
1052 -> std::tuple<etl::tuple_element_t<Indices, TEtl_Tuple>...>
1053 {
1054 return std::tuple<etl::tuple_element_t<Indices, TEtl_Tuple>...>(etl::move(etl::get<Indices>(etl_tuple))...);
1055 }
1056 }
1057
1058 //***************************************************************************
1060 //***************************************************************************
1061 template<typename... TTypes>
1062 ETL_NODISCARD
1063 ETL_CONSTEXPR14
1064 auto to_std(const etl::tuple<TTypes...>& etl_tuple)
1065 -> std::tuple<etl::decay_t<TTypes>...>
1066 {
1067 return private_tuple::to_std_impl(etl_tuple, etl::make_index_sequence_for<TTypes...>());
1068 }
1069
1070 //***************************************************************************
1072 //***************************************************************************
1073 template<typename... TTypes>
1074 ETL_NODISCARD
1075 ETL_CONSTEXPR14
1076 auto to_std(etl::tuple<TTypes...>&& etl_tuple)
1077 -> std::tuple<etl::decay_t<TTypes>...>
1078 {
1079 return private_tuple::to_std_impl(etl::move(etl_tuple), etl::make_index_sequence_for<TTypes...>());
1080 }
1081
1082 //***************************************************************************
1085 //***************************************************************************
1086 namespace private_tuple
1087 {
1089 template<typename TStd_Tuple, size_t... Indices>
1090 ETL_NODISCARD
1091 ETL_CONSTEXPR14
1092 auto to_etl_impl(const TStd_Tuple& std_tuple, etl::index_sequence<Indices...>)
1093 -> etl::tuple<typename std::tuple_element<Indices, TStd_Tuple>::type...>
1094 {
1095 return etl::tuple<typename std::tuple_element<Indices, TStd_Tuple>::type...>(std::get<Indices>(std_tuple)...);
1096 }
1097
1099 template<typename TStd_Tuple, size_t... Indices>
1100 ETL_NODISCARD
1101 ETL_CONSTEXPR14
1102 auto to_etl_impl(TStd_Tuple&& std_tuple, etl::index_sequence<Indices...>)
1103 -> etl::tuple<typename std::tuple_element<Indices, TStd_Tuple>::type...>
1104 {
1105 return etl::tuple<typename std::tuple_element<Indices, TStd_Tuple>::type...>(std::move(std::get<Indices>(std_tuple))...);
1106 }
1107 }
1108
1109 //***************************************************************************
1111 //***************************************************************************
1112 template<typename... TTypes>
1113 ETL_NODISCARD
1114 ETL_CONSTEXPR14
1115 auto to_etl(const std::tuple<TTypes...>& std_tuple)
1116 -> etl::tuple<etl::decay_t<TTypes>...>
1117 {
1118 return private_tuple::to_etl_impl(std_tuple, etl::make_index_sequence_for<TTypes...>());
1119 }
1120
1121 //***************************************************************************
1123 //***************************************************************************
1124 template<typename... TTypes>
1125 ETL_NODISCARD
1126 ETL_CONSTEXPR14
1127 auto to_etl(std::tuple<TTypes...>&& std_tuple)
1128 -> etl::tuple<etl::decay_t<TTypes>...>
1129 {
1130 return private_tuple::to_etl_impl(etl::move(std_tuple), etl::make_index_sequence_for<TTypes...>());
1131 }
1132#endif
1133
1134 namespace private_tuple
1135 {
1136 //***************************************************************************
1138 //***************************************************************************
1139 // When there are no indices left to compare.
1140 template <typename TTuple1, typename TTuple2>
1141 ETL_NODISCARD
1142 ETL_CONSTEXPR14
1143 bool tuple_equality(const TTuple1& /*lhs*/, const TTuple2& /*rhs*/, etl::index_sequence<>)
1144 {
1145 return true;
1146 }
1147
1148 // Recursive case: compare the current element and recurse.
1149 template <typename TTuple1, typename TTuple2, size_t Index, size_t... Indices>
1150 ETL_NODISCARD
1151 ETL_CONSTEXPR14
1152 bool tuple_equality(const TTuple1& lhs, const TTuple2& rhs, etl::index_sequence<Index, Indices...>)
1153 {
1154 return etl::get<Index>(lhs) == etl::get<Index>(rhs) && tuple_equality(lhs, rhs, etl::index_sequence<Indices...>{});
1155 }
1156
1157 //***************************************************************************
1159 //***************************************************************************
1160 // When there are no indices left to compare.
1161 template <typename TTuple1, typename TTuple2>
1162 ETL_NODISCARD
1163 ETL_CONSTEXPR14
1164 bool tuple_less_than(const TTuple1& /*lhs*/, const TTuple2& /*rhs*/, etl::index_sequence<>)
1165 {
1166 return false;
1167 }
1168
1169 // Recursively compare the current element and the rest.
1170 template <typename TTuple1, typename TTuple2, size_t Index, size_t... Indices>
1171 ETL_NODISCARD
1172 ETL_CONSTEXPR14
1173 bool tuple_less_than(const TTuple1& lhs, const TTuple2& rhs, etl::index_sequence<Index, Indices...>)
1174 {
1175 if (get<Index>(lhs) < get<Index>(rhs))
1176 {
1177 return true;
1178 }
1179
1180 if (get<Index>(rhs) < get<Index>(lhs))
1181 {
1182 return false;
1183 }
1184
1185 return tuple_less_than(lhs, rhs, etl::index_sequence<Indices...>{});
1186 }
1187 }
1188
1189 //***************************************************************************
1191 //***************************************************************************
1192 template <typename... TTypes, typename... UTypes>
1193 ETL_NODISCARD
1194 ETL_CONSTEXPR14
1195 bool operator ==(const etl::tuple<TTypes...>& lhs,
1196 const etl::tuple<UTypes...>& rhs)
1197 {
1198 ETL_STATIC_ASSERT(sizeof...(TTypes) == sizeof...(UTypes), "Cannot compare tuples of different sizes");
1199
1200 // Compare each element of the tuples.
1201 return private_tuple::tuple_equality(lhs, rhs, etl::make_index_sequence<etl::tuple<TTypes...>::size()>{});
1202 }
1203
1204 //***************************************************************************
1206 //***************************************************************************
1207 template <typename... TTypes, typename... UTypes>
1208 ETL_NODISCARD
1209 ETL_CONSTEXPR14
1210 bool operator !=(const etl::tuple<TTypes...>& lhs,
1211 const etl::tuple<UTypes...>& rhs)
1212 {
1213 return !(lhs == rhs);
1214 }
1215
1216 //***************************************************************************
1218 //***************************************************************************
1219 template <typename... TTypes, typename... UTypes>
1220 ETL_NODISCARD
1221 ETL_CONSTEXPR14
1222 bool operator <(const etl::tuple<TTypes...>& lhs,
1223 const etl::tuple<UTypes...>& rhs)
1224 {
1225 ETL_STATIC_ASSERT(sizeof...(TTypes) == sizeof...(UTypes), "Cannot compare tuples of different sizes");
1226
1227 // Compare the elements.
1228 return private_tuple::tuple_less_than(lhs, rhs, etl::make_index_sequence<etl::tuple<TTypes...>::size()>{});
1229 }
1230
1231 //***************************************************************************
1233 //***************************************************************************
1234 template <typename... TTypes, typename... UTypes>
1235 ETL_NODISCARD
1236 ETL_CONSTEXPR14
1237 bool operator <=(const etl::tuple<TTypes...>& lhs,
1238 const etl::tuple<UTypes...>& rhs)
1239 {
1240 return !(rhs < lhs);
1241 }
1242
1243 //***************************************************************************
1245 //***************************************************************************
1246 template <typename... TTypes, typename... UTypes>
1247 ETL_NODISCARD
1248 ETL_CONSTEXPR14
1249 bool operator >(const etl::tuple<TTypes...>& lhs,
1250 const etl::tuple<UTypes...>& rhs)
1251 {
1252 return (rhs < lhs);
1253 }
1254
1255 //***************************************************************************
1257 //***************************************************************************
1258 template <typename... TTypes, typename... UTypes>
1259 ETL_NODISCARD
1260 ETL_CONSTEXPR14
1261 bool operator >=(const etl::tuple<TTypes...>& lhs,
1262 const etl::tuple<UTypes...>& rhs)
1263 {
1264 return !(lhs < rhs);
1265 }
1266
1267 //***************************************************************************
1269 //***************************************************************************
1270 template <typename... TTypes>
1271 ETL_CONSTEXPR14
1272 void swap(etl::tuple<TTypes...>& lhs, etl::tuple<TTypes...>& rhs)
1273 {
1274 lhs.swap(rhs);
1275 }
1276}
1277
1278namespace std
1279{
1280#if ETL_NOT_USING_STL && !((defined(ETL_DEVELOPMENT_OS_APPLE) || \
1281 (ETL_COMPILER_FULL_VERSION >= 190000)) && defined(ETL_COMPILER_CLANG))
1282 template <typename T>
1283 struct tuple_size;
1284
1285 template <size_t Index, typename TType>
1286 struct tuple_element;
1287#endif
1288
1289 //***************************************************************************
1291 //***************************************************************************
1292 template <typename... Types>
1293 struct tuple_size<etl::tuple<Types...>> : etl::integral_constant<size_t, sizeof...(Types)>
1294 {
1295 };
1296
1297 //***************************************************************************
1299 //***************************************************************************
1300 template <size_t Index, typename... Types>
1301 struct tuple_element<Index, etl::tuple<Types...>>
1302 {
1303 using type = typename etl::nth_type_t<Index, Types...>;
1304 };
1305}
1306
1307#endif
1308#endif
void swap(etl::array_view< T > &lhs, etl::array_view< T > &rhs) ETL_NOEXCEPT
Swaps the values.
Definition array_view.h:650
integral_constant< bool, false > false_type
integral_constant specialisations
Definition type_traits_generator.h:899
bitset_ext
Definition absolute.h:39
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:838
bool operator>(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1190
bool operator>=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1202
bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1151
ETL_CONSTEXPR TContainer::size_type size(const TContainer &container)
Definition iterator.h:1187
bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1139
T & get(array< T, Size > &a)
Definition array.h:1216
bool operator<(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1163
bool operator<=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1178
Definition tuple_size.h:38