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 "functional.h"
45 #include "nth_type.h"
46 #include "type_list.h"
47 #include "type_traits.h"
48 #include "utility.h"
49
51 #include "private/tuple_size.h"
52
53namespace etl
54{
55 //***************************************************************************
58 //***************************************************************************
59 template <typename... TTypes>
60 class tuple;
61
62 //***************************************************************************
65 //***************************************************************************
66 template <typename T>
67 struct is_tuple : etl::false_type
68 {
69 };
70
71 //***************************************************************************
74 //***************************************************************************
75 template <typename... TTypes>
76 struct is_tuple<etl::tuple<TTypes...>> : etl::true_type
77 {
78 };
79
80 namespace private_tuple
81 {
82 //***************************************************************************
84 //***************************************************************************
85 template <typename T, typename TTuple>
86 struct tuple_type_base;
87
88 // Specialisation for an empty tuple
89 template <typename T>
90 struct tuple_type_base<T, tuple<>>
91 {
92 using type = void;
93 };
94
95 // Recursive definition of the type.
96 template <typename T, typename THead, typename... TTail>
97 struct tuple_type_base<T, tuple<THead, TTail...>>
98 {
99 using type = etl::conditional_t<etl::is_same<T, THead>::value, tuple<THead, TTail...>, typename tuple_type_base<T, tuple<TTail...>>::type>;
100 };
101
102 // Get the base of a tuple type whose head type is T.
103 template <typename T, typename TTuple>
104 using tuple_type_base_t = typename tuple_type_base<T, TTuple>::type;
105
106 //***************************************************************************
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 } // namespace private_tuple
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 type_list = etl::type_list<>;
135 using index_sequence_type = etl::make_index_sequence<0>;
136
137 //*********************************
138 // No-op copy_assignment for the base case
139 //*********************************
140 ETL_CONSTEXPR14 void copy_assignment(const this_type& /*other*/)
141 {
142 }
143
144 //*********************************
145 // No-op forward_assignment for the base case
146 //*********************************
147 ETL_CONSTEXPR14 void forward_assignment(this_type&& /*other*/)
148 {
149 }
150
151 //*********************************
152 // No-op swap for the base case
153 //*********************************
154 ETL_CONSTEXPR14 void swap(this_type& /*other*/)
155 {
156 }
157
158 //*********************************
159 // Returns the size of the base case.
160 // Always zero.
161 //*********************************
162 ETL_NODISCARD ETL_CONSTEXPR static size_t size()
163 {
164 return 0U;
165 }
166 };
167
168 //***************************************************************************
170 //***************************************************************************
171 template <typename THead, typename... TTail>
172 class tuple<THead, TTail...> : public tuple<TTail...>
173 {
174 private:
175
176 //*********************************
179 //*********************************
180 template <typename... UTypes>
181 static constexpr size_t number_of_types()
182 {
183 return sizeof...(UTypes);
184 }
185
186 public:
187
188 //*********************************
190 //*********************************
191 template <typename... UTypes>
192 friend class tuple;
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 etl::tuple_element_t<Index, etl::tuple<TTypes...>>&& get(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 <size_t Index, typename... TTypes>
204 ETL_CONSTEXPR14 friend const etl::tuple_element_t<Index, etl::tuple<TTypes...>>&& get(const 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 T&& get(tuple<TTypes...>&&);
211
212 template <typename T, typename... TTypes>
213 ETL_CONSTEXPR14 friend const T& get(const tuple<TTypes...>&);
214
215 template <typename T, typename... TTypes>
216 ETL_CONSTEXPR14 friend const T&& get(const tuple<TTypes...>&&);
217
218 //*********************************
220 //*********************************
221 using value_type = THead;
222 using this_type = tuple<THead, TTail...>;
223 using base_type = tuple<TTail...>;
224 using type_list = etl::type_list<THead, TTail...>;
225 using index_sequence_type = etl::make_index_sequence< number_of_types< THead, TTail...>()>;
227
228 //*********************************
230 //*********************************
231 ETL_CONSTEXPR14 tuple()
232 : value()
233 {
234 }
235
236 //*********************************
238 //*********************************
239 ETL_CONSTEXPR14 tuple(const tuple<THead, TTail...>& other) = default;
240
241 //*********************************
243 //*********************************
244 ETL_CONSTEXPR14 tuple(tuple<THead, TTail...>&& other) = default;
245
246 //*********************************
248 //*********************************
249 ETL_CONSTEXPR14 tuple& operator=(const tuple<THead, TTail...>& other) = default;
250
251 //*********************************
253 //*********************************
254 ETL_CONSTEXPR14 tuple& operator=(tuple<THead, TTail...>&& other) = default;
255
256 //*********************************
259 //*********************************
260 template < typename UHead, typename... UTail,
261 etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>())
262 && (number_of_types<THead, TTail...>() >= 1U) && etl::is_convertible<UHead, THead>::value,
263 int> = 0>
264 ETL_CONSTEXPR14 tuple(tuple<UHead, UTail...>& other)
265 : base_type(other.get_base())
266 , value(other.get_value())
267 {
268 }
269
270 //*********************************
273 //*********************************
274 template < typename UHead, typename... UTail,
275 etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>())
276 && (number_of_types<THead, TTail...>() >= 1U) && !etl::is_convertible<UHead, THead>::value,
277 int> = 0>
278 ETL_CONSTEXPR14 explicit tuple(tuple<UHead, UTail...>& other)
279 : base_type(other.get_base())
280 , value(other.get_value())
281 {
282 }
283
284 //*********************************
287 //*********************************
288 template < typename UHead, typename... UTail,
289 etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>())
290 && (number_of_types<THead, TTail...>() >= 1U) && etl::is_convertible<UHead, THead>::value,
291 int> = 0>
292 ETL_CONSTEXPR14 tuple(const tuple<UHead, UTail...>& other)
293 : base_type(other.get_base())
294 , value(other.get_value())
295 {
296 }
297
298 //*********************************
301 //*********************************
302 template < typename UHead, typename... UTail,
303 etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>())
304 && (number_of_types<THead, TTail...>() >= 1U) && !etl::is_convertible<UHead, THead>::value,
305 int> = 0>
306 ETL_CONSTEXPR14 explicit tuple(const tuple<UHead, UTail...>& other)
307 : base_type(other.get_base())
308 , value(other.get_value())
309 {
310 }
311
312 //*********************************
315 //*********************************
316 template < typename UHead, typename... UTail,
317 etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>())
318 && (number_of_types<THead, TTail...>() >= 1U) && etl::is_convertible<UHead, THead>::value,
319 int> = 0>
320 ETL_CONSTEXPR14 tuple(tuple<UHead, UTail...>&& other)
321 : base_type(etl::forward<tuple<UTail...>>(other.get_base()))
322 , value(etl::forward<UHead>(other.get_value()))
323 {
324 }
325
326 //*********************************
329 //*********************************
330 template < typename UHead, typename... UTail,
331 etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>())
332 && (number_of_types<THead, TTail...>() >= 1U) && !etl::is_convertible<UHead, THead>::value,
333 int> = 0>
334 ETL_CONSTEXPR14 explicit tuple(tuple<UHead, UTail...>&& other)
335 : base_type(etl::forward<tuple<UTail...>>(other.get_base()))
336 , value(etl::forward<UHead>(other.get_value()))
337 {
338 }
339
340 //*********************************
343 //*********************************
344 template < typename UHead, typename... UTail,
345 etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>())
346 && (number_of_types<THead, TTail...>() >= 1U) && etl::is_convertible<UHead, THead>::value,
347 int> = 0>
348 ETL_CONSTEXPR14 tuple(const tuple<UHead, UTail...>&& other)
349 : base_type(other.get_base())
350 , value(other.get_value())
351 {
352 }
353
354 //*********************************
357 //*********************************
358 template < typename UHead, typename... UTail,
359 etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>())
360 && (number_of_types<THead, TTail...>() >= 1U) && !etl::is_convertible<UHead, THead>::value,
361 int> = 0>
362 ETL_CONSTEXPR14 explicit tuple(const tuple<UHead, UTail...>&& other)
363 : base_type(other.get_base())
364 , value(other.get_value())
365 {
366 }
367
368 //*********************************
370 //*********************************
371 ETL_CONSTEXPR14 tuple(const THead& head, const TTail&... tail)
372 : base_type(tail...)
373 , value(head)
374 {
375 }
376
377 //*********************************
380 //*********************************
381 template <
382 typename UHead, typename... UTail,
383 etl::enable_if_t< !is_tuple<etl::remove_reference_t<UHead>>::value && (number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>())
384 && (number_of_types<THead, TTail...>() >= 1U) && etl::is_convertible<UHead, THead>::value,
385 int> = 0>
386 ETL_CONSTEXPR14 tuple(UHead&& head, UTail&&... tail) ETL_NOEXCEPT
387 : base_type(etl::forward<UTail>(tail)...)
388 , value(etl::forward<UHead>(head))
389 {
390 }
391
392 //*********************************
395 //*********************************
396 template <
397 typename UHead, typename... UTail,
398 etl::enable_if_t<!is_tuple<etl::remove_reference_t<UHead>>::value && (number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>())
399 && (number_of_types<THead, TTail...>() >= 1U) && !etl::is_convertible<UHead, THead>::value,
400 int> = 0>
401 ETL_CONSTEXPR14 explicit tuple(UHead&& head, UTail&&... tail) ETL_NOEXCEPT
402 : base_type(etl::forward<UTail>(tail)...)
403 , value(etl::forward<UHead>(head))
404 {
405 }
406
407 //*********************************
410 //*********************************
411 template <typename U1, typename U2,
412 etl::enable_if_t<number_of_types<THead, TTail...>() == 2U && etl::is_convertible<U1, THead>::value
413 && etl::is_convertible< U2, typename base_type::value_type>::value,
414 int> = 0>
415 ETL_CONSTEXPR14 tuple(ETL_OR_STD::pair<U1, U2>& p) ETL_NOEXCEPT
416 : base_type(p.second)
417 , value(p.first)
418 {
419 }
420
421 //*********************************
424 //*********************************
425 template < typename U1, typename U2,
426 etl::enable_if_t<number_of_types<THead, TTail...>() == 2U
427 && (!etl::is_convertible<U1, THead>::value || !etl::is_convertible< U2, typename base_type::value_type>::value),
428 int> = 0>
429 ETL_CONSTEXPR14 explicit tuple(ETL_OR_STD::pair<U1, U2>& p) ETL_NOEXCEPT
430 : base_type(p.second)
431 , value(p.first)
432 {
433 }
434
435 //*********************************
438 //*********************************
439 template <typename U1, typename U2,
440 etl::enable_if_t<number_of_types<THead, TTail...>() == 2U && etl::is_convertible<U1, THead>::value
441 && etl::is_convertible< U2, typename base_type::value_type>::value,
442 int> = 0>
443 ETL_CONSTEXPR14 tuple(const ETL_OR_STD::pair<U1, U2>& p) ETL_NOEXCEPT
444 : base_type(p.second)
445 , value(p.first)
446 {
447 }
448
449 //*********************************
452 //*********************************
453 template < typename U1, typename U2,
454 etl::enable_if_t<number_of_types<THead, TTail...>() == 2U
455 && (!etl::is_convertible<U1, THead>::value || !etl::is_convertible< U2, typename base_type::value_type>::value),
456 int> = 0>
457 ETL_CONSTEXPR14 explicit tuple(const ETL_OR_STD::pair<U1, U2>& p) ETL_NOEXCEPT
458 : base_type(p.second)
459 , value(p.first)
460 {
461 }
462
463 //*********************************
466 //*********************************
467 template <typename U1, typename U2,
468 etl::enable_if_t<number_of_types<THead, TTail...>() == 2U && etl::is_convertible<U1, THead>::value
469 && etl::is_convertible< U2, typename base_type::value_type>::value,
470 int> = 0>
471 ETL_CONSTEXPR14 tuple(ETL_OR_STD::pair<U1, U2>&& p) ETL_NOEXCEPT
472 : base_type(etl::forward<U2>(p.second))
473 , value(etl::forward<U1>(p.first))
474 {
475 }
476
477 //*********************************
480 //*********************************
481 template < typename U1, typename U2,
482 etl::enable_if_t<number_of_types<THead, TTail...>() == 2U
483 && (!etl::is_convertible<U1, THead>::value || !etl::is_convertible< U2, typename base_type::value_type>::value),
484 int> = 0>
485 ETL_CONSTEXPR14 explicit tuple(ETL_OR_STD::pair<U1, U2>&& p) ETL_NOEXCEPT
486 : base_type(etl::forward<U2>(p.second))
487 , value(etl::forward<U1>(p.first))
488 {
489 }
490
491 //*********************************
494 //*********************************
495 template <typename U1, typename U2,
496 etl::enable_if_t<number_of_types<THead, TTail...>() == 2U && etl::is_convertible<U1, THead>::value
497 && etl::is_convertible< U2, typename base_type::value_type>::value,
498 int> = 0>
499 ETL_CONSTEXPR14 tuple(const ETL_OR_STD::pair<U1, U2>&& p) ETL_NOEXCEPT
500 : base_type(etl::forward<const U2>(p.second))
501 , value(etl::forward<const U1>(p.first))
502 {
503 }
504
505 //*********************************
508 //*********************************
509 template < typename U1, typename U2,
510 etl::enable_if_t<number_of_types<THead, TTail...>() == 2U
511 && (!etl::is_convertible<U1, THead>::value || !etl::is_convertible< U2, typename base_type::value_type>::value),
512 int> = 0>
513 ETL_CONSTEXPR14 explicit tuple(const ETL_OR_STD::pair<U1, U2>&& p) ETL_NOEXCEPT
514 : base_type(etl::forward<const U2>(p.second))
515 , value(etl::forward<const U1>(p.first))
516 {
517 }
518
519 //*********************************
521 //*********************************
522 template < typename UHead, typename... UTail,
523 etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>()), int> = 0>
524 ETL_CONSTEXPR14 tuple& operator=(const tuple<UHead, UTail...>& other)
525 {
526 copy_assignment(other);
527
528 return *this;
529 }
530
531 //*********************************
533 //*********************************
534 template < typename UHead, typename... UTail,
535 etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>()), int> = 0>
536 ETL_CONSTEXPR14 tuple& operator=(tuple<UHead, UTail...>&& other)
537 {
538 forward_assignment(etl::forward<tuple<UHead, UTail...>>(other));
539
540 return *this;
541 }
542
543 //*********************************
545 //*********************************
546 template <typename U1, typename U2, size_t NTypes = number_of_types<THead, TTail...>(), etl::enable_if_t<NTypes == 2U, int> = 0>
547 ETL_CONSTEXPR14 tuple& operator=(ETL_OR_STD::pair<U1, U2>& p)
548 {
549 get_value() = p.first;
550 get_base().get_value() = p.second;
551
552 return *this;
553 }
554
555 //*********************************
557 //*********************************
558 template <typename U1, typename U2, size_t NTypes = number_of_types<THead, TTail...>(), etl::enable_if_t<NTypes == 2U, int> = 0>
559 ETL_CONSTEXPR14 tuple& operator=(const ETL_OR_STD::pair<U1, U2>& p)
560 {
561 get_value() = p.first;
562 get_base().get_value() = p.second;
563
564 return *this;
565 }
566
567 //*********************************
569 //*********************************
570 template <typename U1, typename U2, size_t NTypes = number_of_types<THead, TTail...>(), etl::enable_if_t<NTypes == 2U, int> = 0>
571 ETL_CONSTEXPR14 tuple& operator=(ETL_OR_STD::pair<U1, U2>&& p)
572 {
573 get_value() = etl::forward<U1>(p.first);
574 get_base().get_value() = etl::forward<U2>(p.second);
575
576 return *this;
577 }
578
579 //*********************************
581 //*********************************
582 template <typename U1, typename U2, size_t NTypes = number_of_types<THead, TTail...>(), etl::enable_if_t<NTypes == 2U, int> = 0>
583 ETL_CONSTEXPR14 tuple& operator=(const ETL_OR_STD::pair<U1, U2>&& p)
584 {
585 get_value() = etl::forward<const U1>(p.first);
586 get_base().get_value() = etl::forward<const U2>(p.second);
587
588 return *this;
589 }
590
591 //*********************************
593 //*********************************
594 ETL_CONSTEXPR14 void swap(this_type& other)
595 {
596 using ETL_OR_STD::swap;
597
598 // Swap the head
599 swap(get_value(), other.get_value());
600
601 auto& this_base = get_base();
602 auto& other_base = other.get_base();
603
604 // Recursively swap the tail by calling the base class's swap
605 // implementation.
606 this_base.swap(other_base);
607 }
608
609 //*********************************
611 //*********************************
612 ETL_NODISCARD
613 constexpr static size_t size()
614 {
615 return number_of_types<THead, TTail...>();
616 }
617
618 protected:
619
620 //*********************************
622 //*********************************
623 ETL_NODISCARD ETL_CONSTEXPR14 THead& get_value()
624 {
625 return value;
626 }
627
628 //*********************************
630 //*********************************
631 ETL_CONSTEXPR const THead& get_value() const
632 {
633 return value;
634 }
635
636 //*********************************
638 //*********************************
639 ETL_NODISCARD ETL_CONSTEXPR14 base_type& get_base()
640 {
641 return static_cast<base_type&>(*this);
642 }
643
644 //*********************************
646 //*********************************
647 ETL_NODISCARD ETL_CONSTEXPR14 const base_type& get_base() const
648 {
649 return static_cast<const base_type&>(*this);
650 }
651
652 //*********************************
654 //*********************************
655 template <typename UHead, typename... UTail>
656 ETL_CONSTEXPR14 void copy_assignment(const tuple<UHead, UTail...>& other)
657 {
658 // Assign the head
659 this->value = other.get_value();
660
661 // Get the base classes
662 auto& this_base = get_base();
663 const auto& other_base = other.get_base();
664
665 // Recursively assign the tail by calling the base class's assignment
666 // implementation
667 this_base.copy_assignment(other_base);
668 }
669
670 //*********************************
672 //*********************************
673 template <typename UHead, typename... UTail>
674 ETL_CONSTEXPR14 void forward_assignment(tuple<UHead, UTail...>&& other)
675 {
676 // Assign the head
677 this->value = etl::forward<UHead>(other.get_value());
678
679 auto& this_base = get_base();
680 auto&& other_base = other.get_base();
681
682 // Recursively assign the tail by calling the base class's move assignment
683 // implementation
684 this_base.forward_assignment(etl::forward<tuple<UTail...>>(other_base));
685 }
686
687 private:
688
689 THead value;
690 };
691
692 #if ETL_USING_CPP17
693 //***************************************************************************
695 //***************************************************************************
696 template <typename... TArgs>
697 tuple(TArgs... args) -> tuple<TArgs...>;
698
699 //***************************************************************************
701 //***************************************************************************
702 template <typename T1, typename T2>
703 tuple(ETL_OR_STD::pair<T1, T2>) -> tuple<T1, T2>;
704 #endif
705
706 //***************************************************************************
708 //***************************************************************************
709 template <size_t Index, typename... TTypes>
710 struct tuple_element<Index, etl::tuple<TTypes...>>
711 {
712 using type = etl::nth_type_t<Index, TTypes...>;
713 };
714
715 //***************************************************************************
717 //***************************************************************************
718 template <typename... TTypes>
719 struct tuple_size<etl::tuple<TTypes...>> : etl::integral_constant<size_t, sizeof...(TTypes)>
720 {
721 };
722
723 //***************************************************************************
725 //***************************************************************************
726 template <typename... Types>
727 struct common_type<etl::tuple<Types...>>
728 {
729 using type = etl::common_type_t<Types...>;
730 };
731
732 //***************************************************************************
736 //***************************************************************************
737 template <size_t Index, typename... TTypes>
738 ETL_NODISCARD ETL_CONSTEXPR14 etl::tuple_element_t<Index, etl::tuple<TTypes...>>& get(tuple<TTypes...>& t)
739 {
740 ETL_STATIC_ASSERT(Index < sizeof...(TTypes), "etl::get<Index> - Index out of range");
741
742 // Get the type at this index.
743 using tuple_type = etl::nth_base_t<Index, tuple<TTypes...>>&;
744
745 // Cast the tuple to the selected type and get the value.
746 return static_cast<tuple_type>(t).get_value();
747 }
748
749 //***************************************************************************
753 //***************************************************************************
754 template <size_t Index, typename... TTypes>
755 ETL_NODISCARD ETL_CONSTEXPR14 const etl::tuple_element_t<Index, etl::tuple<TTypes...>>& get(const tuple<TTypes...>& t)
756 {
757 ETL_STATIC_ASSERT(Index < sizeof...(TTypes), "etl::get<Index> - Index out of range");
758
759 // Get the type at this index.
760 using tuple_type = const etl::nth_base_t<Index, tuple<TTypes...>>&;
761
762 // Cast the tuple to the selected type and get the value.
763 return static_cast<tuple_type>(t).get_value();
764 }
765
766 //***************************************************************************
770 //***************************************************************************
771 template <size_t Index, typename... TTypes>
772 ETL_NODISCARD ETL_CONSTEXPR14 etl::tuple_element_t<Index, etl::tuple<TTypes...>>&& get(tuple<TTypes...>&& t)
773 {
774 ETL_STATIC_ASSERT(Index < sizeof...(TTypes), "etl::get<Index> - Index out of range");
775
776 // Get the type at this index.
777 using tuple_type = etl::nth_base_t<Index, tuple<TTypes...>>&&;
778
779 // Cast the tuple to the selected type and get the value.
780 return etl::move(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
796 // Cast the tuple to the selected type and get the value.
797 return etl::move(static_cast<tuple_type>(t).get_value());
798 }
799
800 //***************************************************************************
804 //***************************************************************************
805 template <typename T, typename... TTypes>
806 ETL_NODISCARD ETL_CONSTEXPR14 T& get(tuple<TTypes...>& t)
807 {
808 ETL_STATIC_ASSERT(!(etl::has_duplicates_of<T, TTypes...>::value), "etl::get<Type> - Tuple contains duplicate instances of T");
809 ETL_STATIC_ASSERT((etl::is_one_of<T, TTypes...>::value), "etl::get<Type> - Tuple does not contain the specified type");
810
811 // Get the tuple base type that contains a T
812 using tuple_type = etl::private_tuple::tuple_type_base_t<T, tuple<TTypes...>>&;
813
814 // Cast the tuple to the selected type and get the value.
815 return static_cast<tuple_type>(t).get_value();
816 }
817
818 //***************************************************************************
822 //***************************************************************************
823 template <typename T, typename... TTypes>
824 ETL_NODISCARD ETL_CONSTEXPR14 const T& get(const tuple<TTypes...>& t)
825 {
826 ETL_STATIC_ASSERT(!(etl::has_duplicates_of<T, TTypes...>::value), "etl::get<Type> - Tuple contains duplicate instances of T");
827 ETL_STATIC_ASSERT((etl::is_one_of<T, TTypes...>::value), "etl::get<Type> - Tuple does not contain the specified type");
828
829 // Get the tuple base type that contains a T
830 using tuple_type = const etl::private_tuple::tuple_type_base_t<T, tuple<TTypes...>>&;
831
832 // Cast the tuple to the selected type and get the value.
833 return static_cast<tuple_type>(t).get_value();
834 }
835
836 //***************************************************************************
840 //***************************************************************************
841 template <typename T, typename... TTypes>
842 ETL_NODISCARD ETL_CONSTEXPR14 T&& get(tuple<TTypes...>&& t)
843 {
844 ETL_STATIC_ASSERT(!(etl::has_duplicates_of<T, TTypes...>::value), "etl::get<Type> - Tuple contains duplicate instances of T");
845 ETL_STATIC_ASSERT((etl::is_one_of<T, TTypes...>::value), "etl::get<Type> - Tuple does not contain the specified type");
846
847 // Get the tuple base type that contains a T
848 using tuple_type = etl::private_tuple::tuple_type_base_t<T, tuple<TTypes...>>&&;
849
850 // Cast the tuple to the selected type and get the value.
851 return etl::move(static_cast<tuple_type>(t).get_value());
852 }
853
854 //***************************************************************************
858 //***************************************************************************
859 template <typename T, typename... TTypes>
860 ETL_NODISCARD ETL_CONSTEXPR14 const T&& get(const tuple<TTypes...>&& t)
861 {
862 ETL_STATIC_ASSERT(!(etl::has_duplicates_of<T, TTypes...>::value), "etl::get<Type> - Tuple contains duplicate instances of T");
863 ETL_STATIC_ASSERT((etl::is_one_of<T, TTypes...>::value), "etl::get<Type> - Tuple does not contain the specified type");
864
865 // Get the tuple base type that contains a T
866 using tuple_type = const etl::private_tuple::tuple_type_base_t<T, tuple<TTypes...>>&&;
867
868 // Cast the tuple to the selected type and get the value.
869 return etl::move(static_cast<tuple_type>(t).get_value());
870 }
871
872 #if ETL_USING_CPP17
873 inline constexpr private_tuple::ignore_t ignore;
874 #else
875 static constexpr private_tuple::ignore_t ignore;
876 #endif
877
878 //***************************************************************************
880 //***************************************************************************
881 template <typename... TTypes>
882 ETL_CONSTEXPR etl::tuple<TTypes&...> tie(TTypes&... args)
883 {
884 return {args...};
885 }
886
887 //***************************************************************************
888 // Creates a tuple from the provided arguments.
889 //***************************************************************************
890 template <typename... TTypes>
891 ETL_NODISCARD ETL_CONSTEXPR14 etl::tuple<etl::unwrap_ref_decay_t<TTypes>...> make_tuple(TTypes&&... args)
892 {
893 return etl::tuple<unwrap_ref_decay_t<TTypes>...>(etl::forward<TTypes>(args)...);
894 }
895
896 //***************************************************************************
900 //***************************************************************************
901 template <typename TTuple, size_t... Indices>
902 ETL_NODISCARD ETL_CONSTEXPR14 auto select_from_tuple(TTuple&& tuple,
903 etl::index_sequence<Indices...>) -> etl::tuple<etl::tuple_element_t<Indices, etl::decay_t<TTuple>>...>
904 {
905 ETL_STATIC_ASSERT(sizeof...(Indices) <= etl::tuple_size<etl::decay_t<TTuple>>::value, "Number of indices is greater than the tuple size");
906
907 return etl::make_tuple(etl::forward<etl::tuple_element_t<Indices, etl::decay_t<TTuple>>>(etl::get<Indices>(etl::forward<TTuple>(tuple)))...);
908 }
909
910 //***************************************************************************
914 //***************************************************************************
915 template <size_t... Indices, typename TTuple>
916 ETL_NODISCARD ETL_CONSTEXPR14 auto select_from_tuple(TTuple&& tuple) -> etl::tuple<etl::tuple_element_t<Indices, etl::decay_t<TTuple>>...>
917 {
918 return select_from_tuple(etl::forward<TTuple>(tuple), etl::index_sequence<Indices...>{});
919 }
920
921 //***************************************************************************
923 //***************************************************************************
924 template <typename... TTypes>
925 ETL_NODISCARD ETL_CONSTEXPR14 etl::tuple<TTypes&&...> forward_as_tuple(TTypes&&... args)
926 {
927 return tuple<TTypes&&...>(etl::forward<TTypes>(args)...);
928 }
929
930 namespace private_tuple
931 {
932 //**********************************
933 // Helper to concatenate two tuples
934 //**********************************
935 template <typename Tuple1, typename Tuple2, size_t... Index1, size_t... Index2>
936 ETL_CONSTEXPR14 auto tuple_cat_impl(Tuple1&& t1, etl::index_sequence<Index1...>, Tuple2&& t2, etl::index_sequence<Index2...>)
937 -> etl::tuple<etl::tuple_element_t<Index1, etl::decay_t<Tuple1>>..., etl::tuple_element_t<Index2, etl::decay_t<Tuple2>>...>
938 {
939 return etl::tuple<etl::tuple_element_t<Index1, etl::decay_t<Tuple1>>..., etl::tuple_element_t<Index2, etl::decay_t<Tuple2>>...>(
940 etl::get<Index1>(etl::forward<Tuple1>(t1))..., etl::get<Index2>(etl::forward<Tuple2>(t2))...);
941 }
942 } // namespace private_tuple
943
944 //***************************************************************************
946 //***************************************************************************
947 template <typename Tuple>
948 ETL_NODISCARD ETL_CONSTEXPR14 auto tuple_cat(Tuple&& t) -> Tuple
949 {
950 return etl::forward<Tuple>(t);
951 }
952
953 //***************************************************************************
955 //***************************************************************************
956 template <typename Tuple1, typename Tuple2, typename... Tuples>
957 ETL_NODISCARD ETL_CONSTEXPR14 auto tuple_cat(Tuple1&& t1, Tuple2&& t2, Tuples&&... ts)
958 -> decltype(tuple_cat(private_tuple::tuple_cat_impl(etl::forward<Tuple1>(t1),
959 etl::make_index_sequence< etl::tuple_size<etl::decay_t<Tuple1>>::value>{},
960 etl::forward<Tuple2>(t2),
961 etl::make_index_sequence< etl::tuple_size<etl::decay_t<Tuple2>>::value>{}),
962 etl::forward<Tuples>(ts)...))
963 {
964 return tuple_cat(
965 private_tuple::tuple_cat_impl(etl::forward<Tuple1>(t1), etl::make_index_sequence< etl::tuple_size<etl::decay_t<Tuple1>>::value>{},
966 etl::forward<Tuple2>(t2), etl::make_index_sequence< etl::tuple_size<etl::decay_t<Tuple2>>::value>{}),
967 etl::forward<Tuples>(ts)...);
968 }
969
970 #if ETL_USING_STL
971 //***************************************************************************
972 // Tuple conversion functions.
973 // From ETL to STL
974 //***************************************************************************
975 namespace private_tuple
976 {
978 template <typename TEtl_Tuple, size_t... Indices>
979 ETL_NODISCARD ETL_CONSTEXPR14 auto to_std_impl(const TEtl_Tuple& etl_tuple,
980 etl::index_sequence<Indices...>) -> std::tuple<typename etl::tuple_element_t<Indices, TEtl_Tuple>...>
981 {
982 return std::tuple<etl::tuple_element_t<Indices, TEtl_Tuple>...>(etl::get<Indices>(etl_tuple)...);
983 }
984
986 template <typename TEtl_Tuple, size_t... Indices>
987 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>...>
988 {
989 return std::tuple<etl::tuple_element_t<Indices, TEtl_Tuple>...>(etl::move(etl::get<Indices>(etl_tuple))...);
990 }
991 } // namespace private_tuple
992
993 //***************************************************************************
995 //***************************************************************************
996 template <typename... TTypes>
997 ETL_NODISCARD ETL_CONSTEXPR14 auto to_std(const etl::tuple<TTypes...>& etl_tuple) -> std::tuple<etl::decay_t<TTypes>...>
998 {
999 return private_tuple::to_std_impl(etl_tuple, etl::make_index_sequence_for<TTypes...>());
1000 }
1001
1002 //***************************************************************************
1004 //***************************************************************************
1005 template <typename... TTypes>
1006 ETL_NODISCARD ETL_CONSTEXPR14 auto to_std(etl::tuple<TTypes...>&& etl_tuple) -> std::tuple<etl::decay_t<TTypes>...>
1007 {
1008 return private_tuple::to_std_impl(etl::move(etl_tuple), etl::make_index_sequence_for<TTypes...>());
1009 }
1010
1011 //***************************************************************************
1014 //***************************************************************************
1015 namespace private_tuple
1016 {
1018 template <typename TStd_Tuple, size_t... Indices>
1019 ETL_NODISCARD ETL_CONSTEXPR14 auto to_etl_impl(const TStd_Tuple& std_tuple,
1020 etl::index_sequence<Indices...>) -> etl::tuple<typename std::tuple_element<Indices, TStd_Tuple>::type...>
1021 {
1022 return etl::tuple< typename std::tuple_element<Indices, TStd_Tuple>::type...>(std::get<Indices>(std_tuple)...);
1023 }
1024
1026 template <typename TStd_Tuple, size_t... Indices>
1027 ETL_NODISCARD ETL_CONSTEXPR14 auto to_etl_impl(TStd_Tuple&& std_tuple,
1028 etl::index_sequence<Indices...>) -> etl::tuple<typename std::tuple_element<Indices, TStd_Tuple>::type...>
1029 {
1030 return etl::tuple< typename std::tuple_element<Indices, TStd_Tuple>::type...>(std::move(std::get<Indices>(std_tuple))...);
1031 }
1032 } // namespace private_tuple
1033
1034 //***************************************************************************
1036 //***************************************************************************
1037 template <typename... TTypes>
1038 ETL_NODISCARD ETL_CONSTEXPR14 auto to_etl(const std::tuple<TTypes...>& std_tuple) -> etl::tuple<etl::decay_t<TTypes>...>
1039 {
1040 return private_tuple::to_etl_impl(std_tuple, etl::make_index_sequence_for<TTypes...>());
1041 }
1042
1043 //***************************************************************************
1045 //***************************************************************************
1046 template <typename... TTypes>
1047 ETL_NODISCARD ETL_CONSTEXPR14 auto to_etl(std::tuple<TTypes...>&& std_tuple) -> etl::tuple<etl::decay_t<TTypes>...>
1048 {
1049 return private_tuple::to_etl_impl(etl::move(std_tuple), etl::make_index_sequence_for<TTypes...>());
1050 }
1051 #endif
1052
1053 namespace private_tuple
1054 {
1055 //***************************************************************************
1057 //***************************************************************************
1058 // When there are no indices left to compare.
1059 template <typename TTuple1, typename TTuple2>
1060 ETL_NODISCARD ETL_CONSTEXPR14 bool tuple_equality(const TTuple1& /*lhs*/, const TTuple2& /*rhs*/, etl::index_sequence<>)
1061 {
1062 return true;
1063 }
1064
1065 // Recursive case: compare the current element and recurse.
1066 template <typename TTuple1, typename TTuple2, size_t Index, size_t... Indices>
1067 ETL_NODISCARD ETL_CONSTEXPR14 bool tuple_equality(const TTuple1& lhs, const TTuple2& rhs, etl::index_sequence<Index, Indices...>)
1068 {
1069 return etl::get<Index>(lhs) == etl::get<Index>(rhs) && tuple_equality(lhs, rhs, etl::index_sequence<Indices...>{});
1070 }
1071
1072 //***************************************************************************
1074 //***************************************************************************
1075 // When there are no indices left to compare.
1076 template <typename TTuple1, typename TTuple2>
1077 ETL_NODISCARD ETL_CONSTEXPR14 bool tuple_less_than(const TTuple1& /*lhs*/, const TTuple2& /*rhs*/, etl::index_sequence<>)
1078 {
1079 return false;
1080 }
1081
1082 // Recursively compare the current element and the rest.
1083 template <typename TTuple1, typename TTuple2, size_t Index, size_t... Indices>
1084 ETL_NODISCARD ETL_CONSTEXPR14 bool tuple_less_than(const TTuple1& lhs, const TTuple2& rhs, etl::index_sequence<Index, Indices...>)
1085 {
1086 if (get<Index>(lhs) < get<Index>(rhs))
1087 {
1088 return true;
1089 }
1090
1091 if (get<Index>(rhs) < get<Index>(lhs))
1092 {
1093 return false;
1094 }
1095
1096 return tuple_less_than(lhs, rhs, etl::index_sequence<Indices...>{});
1097 }
1098 } // namespace private_tuple
1099
1100 //***************************************************************************
1102 //***************************************************************************
1103 template <typename... TTypes, typename... UTypes>
1104 ETL_NODISCARD ETL_CONSTEXPR14 bool operator==(const etl::tuple<TTypes...>& lhs, const etl::tuple<UTypes...>& rhs)
1105 {
1106 ETL_STATIC_ASSERT(sizeof...(TTypes) == sizeof...(UTypes), "Cannot compare tuples of different sizes");
1107
1108 // Compare each element of the tuples.
1109 return private_tuple::tuple_equality(lhs, rhs, etl::make_index_sequence<etl::tuple<TTypes...>::size()>{});
1110 }
1111
1112 //***************************************************************************
1114 //***************************************************************************
1115 template <typename... TTypes, typename... UTypes>
1116 ETL_NODISCARD ETL_CONSTEXPR14 bool operator!=(const etl::tuple<TTypes...>& lhs, const etl::tuple<UTypes...>& rhs)
1117 {
1118 return !(lhs == rhs);
1119 }
1120
1121 //***************************************************************************
1123 //***************************************************************************
1124 template <typename... TTypes, typename... UTypes>
1125 ETL_NODISCARD ETL_CONSTEXPR14 bool operator<(const etl::tuple<TTypes...>& lhs, const etl::tuple<UTypes...>& rhs)
1126 {
1127 ETL_STATIC_ASSERT(sizeof...(TTypes) == sizeof...(UTypes), "Cannot compare tuples of different sizes");
1128
1129 // Compare the elements.
1130 return private_tuple::tuple_less_than(lhs, rhs, etl::make_index_sequence<etl::tuple<TTypes...>::size()>{});
1131 }
1132
1133 //***************************************************************************
1135 //***************************************************************************
1136 template <typename... TTypes, typename... UTypes>
1137 ETL_NODISCARD ETL_CONSTEXPR14 bool operator<=(const etl::tuple<TTypes...>& lhs, const etl::tuple<UTypes...>& rhs)
1138 {
1139 return !(rhs < lhs);
1140 }
1141
1142 //***************************************************************************
1144 //***************************************************************************
1145 template <typename... TTypes, typename... UTypes>
1146 ETL_NODISCARD ETL_CONSTEXPR14 bool operator>(const etl::tuple<TTypes...>& lhs, const etl::tuple<UTypes...>& rhs)
1147 {
1148 return (rhs < lhs);
1149 }
1150
1151 //***************************************************************************
1153 //***************************************************************************
1154 template <typename... TTypes, typename... UTypes>
1155 ETL_NODISCARD ETL_CONSTEXPR14 bool operator>=(const etl::tuple<TTypes...>& lhs, const etl::tuple<UTypes...>& rhs)
1156 {
1157 return !(lhs < rhs);
1158 }
1159
1160 //***************************************************************************
1162 //***************************************************************************
1163 template <typename... TTypes>
1164 ETL_CONSTEXPR14 void swap(etl::tuple<TTypes...>& lhs, etl::tuple<TTypes...>& rhs)
1165 {
1166 lhs.swap(rhs);
1167 }
1168
1169 //***************************************************************************
1171 template <typename TList>
1172 struct tuple_from_type_list;
1173
1174 template <typename... TTypes>
1175 struct tuple_from_type_list<etl::type_list<TTypes...>>
1176 {
1177 using type = etl::tuple<TTypes...>;
1178 };
1179
1180 template <typename TTypeList>
1181 using tuple_from_type_list_t = typename tuple_from_type_list<TTypeList>::type;
1182} // namespace etl
1183
1184namespace std
1185{
1186 #if ETL_NOT_USING_STL && !((defined(ETL_DEVELOPMENT_OS_APPLE) || (ETL_COMPILER_FULL_VERSION >= 190000)) && defined(ETL_COMPILER_CLANG))
1187 template <typename T>
1188 struct tuple_size;
1189
1190 template <size_t Index, typename TType>
1191 struct tuple_element;
1192 #endif
1193
1194 //***************************************************************************
1196 //***************************************************************************
1197 template <typename... Types>
1198 struct tuple_size<etl::tuple<Types...>> : etl::integral_constant<size_t, sizeof...(Types)>
1199 {
1200 };
1201
1202 //***************************************************************************
1205 //***************************************************************************
1206 template <size_t Index, typename... Types>
1207 struct tuple_element<Index, etl::tuple<Types...>>
1208 {
1209 using type = etl::nth_type_t<Index, Types...>;
1210 };
1211} // namespace std
1212
1213#endif
1214#endif
void swap(etl::array_view< T > &lhs, etl::array_view< T > &rhs) ETL_NOEXCEPT
Swaps the values.
Definition array_view.h:692
bitset_ext
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:1081
bool operator>(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1133
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:1147
ETL_CONSTEXPR14 bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1093
ETL_CONSTEXPR TContainer::size_type size(const TContainer &container)
Definition iterator.h:1192
T & get(array< T, Size > &a)
Definition array.h:1161
bool operator<(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1106
bool operator<=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1120
Definition tuple_size.h:38