29#ifndef ETL_TUPLE_INCLUDED
30#define ETL_TUPLE_INCLUDED
34#if ETL_NOT_USING_CPP11 && !defined(ETL_IN_UNIT_TEST)
35 #error NOT SUPPORTED FOR C++03 OR BELOW
58 template <
typename...
TTypes>
74 template <
typename...
TTypes>
84 template <
typename T,
typename TTuple>
95 template <
typename T,
typename THead,
typename...
TTail>
99 tuple<THead, TTail...>,
100 typename tuple_type_base<T, tuple<TTail...>>::type>;
104 template <
typename T,
typename TTuple>
115 template <
typename T>
116 ETL_CONSTEXPR ignore_t operator =(T&&) const ETL_NOEXCEPT
131 using value_type =
void;
133 using base_type =
void;
156 void swap(this_type& )
184 template <
typename...
UTypes>
187 return sizeof...(UTypes);
195 template<
typename...
UTypes>
214 template <
typename T,
typename...
TTypes>
218 template <
typename T,
typename...
TTypes>
222 template <
typename T,
typename...
TTypes>
226 template <
typename T,
typename...
TTypes>
233 using value_type =
THead;
277 etl::is_convertible<UHead, THead>::value,
int> = 0>
280 : base_type(
other.get_base())
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>
293 explicit tuple(tuple<UHead, UTail...>& other)
294 : base_type(other.get_base())
295 , value(other.get_value())
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>
307 tuple(
const tuple<UHead, UTail...>& other)
308 : base_type(other.get_base())
309 , value(other.get_value())
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>
321 explicit tuple(
const tuple<UHead, UTail...>& other)
322 : base_type(other.get_base())
323 , value(other.get_value())
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>
335 tuple(tuple<UHead, UTail...>&& other)
336 : base_type(
etl::forward<tuple<UTail...>>(other.get_base()))
337 , value(
etl::forward<UHead>(other.get_value()))
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>
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()))
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>
363 tuple(
const tuple<UHead, UTail...>&& other)
364 : base_type(other.get_base())
365 , value(other.get_value())
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>
377 explicit tuple(
const tuple<UHead, UTail...>&& other)
378 : base_type(other.get_base())
379 , value(other.get_value())
387 tuple(
const THead& head,
const TTail&... tail)
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>
402 tuple(UHead&& head, UTail&&... tail) ETL_NOEXCEPT
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>
417 explicit tuple(UHead&& head, UTail&&... tail) ETL_NOEXCEPT
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>
431 tuple(ETL_OR_STD::pair<U1, U2>& p) ETL_NOEXCEPT
432 : base_type(p.second)
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>
445 explicit tuple(ETL_OR_STD::pair<U1, U2>& p) ETL_NOEXCEPT
446 : base_type(p.second)
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>
459 tuple(
const ETL_OR_STD::pair<U1, U2>& p) ETL_NOEXCEPT
460 : base_type(p.second)
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>
473 explicit tuple(
const ETL_OR_STD::pair<U1, U2>& p) ETL_NOEXCEPT
474 : base_type(p.second)
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>
487 tuple(ETL_OR_STD::pair<U1, U2>&& p) ETL_NOEXCEPT
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>
501 explicit tuple(ETL_OR_STD::pair<U1, U2>&& p) ETL_NOEXCEPT
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>
515 tuple(
const ETL_OR_STD::pair<U1, U2>&& p) ETL_NOEXCEPT
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>
529 explicit tuple(
const ETL_OR_STD::pair<U1, U2>&& p) ETL_NOEXCEPT
530 : base_type(p.second)
538 template <
typename UHead,
typename... UTail,
etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>()),
int> = 0>
540 tuple&
operator =(
const tuple<UHead, UTail...>& other)
542 copy_assignment(other);
550 template <
typename UHead,
typename... UTail,
etl::enable_if_t<(number_of_types<THead, TTail...>() == number_of_types<UHead, UTail...>()),
int> = 0>
552 tuple&
operator =(tuple<UHead, UTail...>&& other)
554 forward_assignment(
etl::forward<tuple<UHead, UTail...>>(other));
564 tuple& operator =(pair<U1, U2>& p)
566 get_value() = p.first;
567 get_base().get_value() = p.second;
577 tuple& operator =(
const pair<U1, U2>& p)
579 get_value() = p.first;
580 get_base().get_value() = p.second;
590 tuple& operator =(pair<U1, U2>&& p)
603 tuple& operator =(
const pair<U1, U2>&& p)
615 void swap(this_type& other)
617 using ETL_OR_STD::swap;
620 swap(get_value(), other.get_value());
622 auto& this_base = get_base();
623 auto& other_base = other.get_base();
626 this_base.swap(other_base);
636 return number_of_types<THead, TTail...>();
655 const THead& get_value()
const
665 base_type& get_base()
667 return static_cast<base_type&
>(*this);
675 const base_type& get_base()
const
677 return static_cast<const base_type&
>(*this);
683 template <
typename UHead,
typename... UTail>
685 void copy_assignment(
const tuple<UHead, UTail...>& other)
688 this->value = other.get_value();
691 auto& this_base = get_base();
692 const auto& other_base = other.get_base();
695 this_base.copy_assignment(other_base);
701 template <
typename UHead,
typename... UTail>
703 void forward_assignment(tuple<UHead, UTail...>&& other)
708 auto& this_base = get_base();
709 auto&& other_base = other.get_base();
712 this_base.forward_assignment(
etl::forward<tuple<UTail...>>(other_base));
724 template <
typename... TArgs>
725 tuple(TArgs... args) -> tuple<TArgs...>;
730 template <
typename T1,
typename T2>
731 tuple(ETL_OR_STD::pair<T1, T2>) -> tuple<T1, T2>;
737 template<
size_t Index,
typename... TTypes>
738 struct tuple_element<Index,
etl::tuple<TTypes...>>
746 template <
typename... TTypes>
747 struct tuple_size<
etl::tuple<TTypes...>>
755 template<
typename... Types>
756 struct common_type<
etl::tuple<Types...>>
766 template <
size_t Index,
typename... TTypes>
771 ETL_STATIC_ASSERT(Index <
sizeof...(TTypes),
"etl::get<Index> - Index out of range");
777 return static_cast<tuple_type
>(t).get_value();
785 template <
size_t Index,
typename... TTypes>
790 ETL_STATIC_ASSERT(Index <
sizeof...(TTypes),
"etl::get<Index> - Index out of range");
796 return static_cast<tuple_type
>(t).get_value();
804 template <
size_t Index,
typename... TTypes>
809 ETL_STATIC_ASSERT(Index <
sizeof...(TTypes),
"etl::get<Index> - Index out of range");
815 return etl::move(
static_cast<tuple_type
>(t).get_value());
823 template <
size_t Index,
typename... TTypes>
828 ETL_STATIC_ASSERT(Index <
sizeof...(TTypes),
"etl::get<Index> - Index out of range");
834 return etl::move(
static_cast<tuple_type
>(t).get_value());
842 template <
typename T,
typename... TTypes>
845 T&
get(tuple<TTypes...>& t)
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");
851 using tuple_type = etl::private_tuple::tuple_type_base_t<T, tuple<TTypes...>>&;
854 return static_cast<tuple_type
>(t).get_value();
862 template <
typename T,
typename... TTypes>
865 const T&
get(
const tuple<TTypes...>& t)
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");
871 using tuple_type =
const etl::private_tuple::tuple_type_base_t<T, tuple<TTypes...>>&;
874 return static_cast<tuple_type
>(t).get_value();
882 template <
typename T,
typename... TTypes>
885 T&&
get(tuple<TTypes...>&& t)
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");
891 using tuple_type = etl::private_tuple::tuple_type_base_t<T, tuple<TTypes...>>&&;
894 return etl::move(
static_cast<tuple_type
>(t).get_value());
902 template <
typename T,
typename... TTypes>
905 const T&&
get(
const tuple<TTypes...>&& t)
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");
911 using tuple_type =
const etl::private_tuple::tuple_type_base_t<T, tuple<TTypes...>>&&;
914 return etl::move(
static_cast<tuple_type
>(t).get_value());
918 inline constexpr private_tuple::ignore_t ignore;
920 static constexpr private_tuple::ignore_t ignore;
926 template <
typename... TTypes>
936 template <
typename... TTypes>
948 template <
typename TTuple,
size_t... Indices>
963 template <
size_t... Indices,
typename TTuple>
966 auto select_from_tuple(TTuple&& tuple)
975 template <
typename... TTypes>
978 etl::tuple<TTypes&&...> forward_as_tuple(TTypes&&... args)
983 namespace private_tuple
988 template <
typename Tuple1,
typename Tuple2,
size_t... Index1,
size_t... Index2>
1002 template <
typename Tuple>
1005 auto tuple_cat(Tuple&& t) -> Tuple
1013 template <
typename Tuple1,
typename Tuple2,
typename... Tuples>
1016 auto tuple_cat(Tuple1&& t1, Tuple2&& t2, Tuples&&... ts)
1035 namespace private_tuple
1038 template<
typename TEtl_Tuple,
size_t... Indices>
1042 -> std::tuple<typename etl::tuple_element_t<Indices, TEtl_Tuple>...>
1044 return std::tuple<etl::tuple_element_t<Indices, TEtl_Tuple>...>(
etl::get<Indices>(etl_tuple)...);
1048 template<
typename TEtl_Tuple,
size_t... Indices>
1052 -> std::tuple<etl::tuple_element_t<Indices, TEtl_Tuple>...>
1054 return std::tuple<etl::tuple_element_t<Indices, TEtl_Tuple>...>(etl::move(
etl::get<Indices>(etl_tuple))...);
1061 template<
typename... TTypes>
1065 -> std::tuple<etl::decay_t<TTypes>...>
1073 template<
typename... TTypes>
1077 -> std::tuple<etl::decay_t<TTypes>...>
1086 namespace private_tuple
1089 template<
typename TStd_Tuple,
size_t... Indices>
1099 template<
typename TStd_Tuple,
size_t... Indices>
1112 template<
typename... TTypes>
1115 auto to_etl(
const std::tuple<TTypes...>& std_tuple)
1124 template<
typename... TTypes>
1127 auto to_etl(std::tuple<TTypes...>&& std_tuple)
1134 namespace private_tuple
1140 template <
typename TTuple1,
typename TTuple2>
1149 template <
typename TTuple1,
typename TTuple2,
size_t I,
size_t... Indices>
1161 template <
typename TTuple1,
typename TTuple2>
1170 template <
typename TTuple1,
typename TTuple2,
size_t I,
size_t... Indices>
1175 if (get<I>(lhs) < get<I>(rhs))
1180 if (get<I>(rhs) < get<I>(lhs))
1192 template <
typename... TTypes,
typename... UTypes>
1198 ETL_STATIC_ASSERT(
sizeof...(TTypes) ==
sizeof...(UTypes),
"Cannot compare tuples of different sizes");
1207 template <
typename... TTypes,
typename... UTypes>
1213 return !(lhs == rhs);
1219 template <
typename... TTypes,
typename... UTypes>
1225 ETL_STATIC_ASSERT(
sizeof...(TTypes) ==
sizeof...(UTypes),
"Cannot compare tuples of different sizes");
1234 template <
typename... TTypes,
typename... UTypes>
1240 return !(rhs < lhs);
1246 template <
typename... TTypes,
typename... UTypes>
1258 template <
typename... TTypes,
typename... UTypes>
1264 return !(lhs < rhs);
1270 template <
typename... TTypes>
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>
1285 template <
size_t I,
typename TType>
1286 struct tuple_element;
1292 template <
typename... Types>
1300 template <
size_t I,
typename... Types>
1301 struct tuple_element<I,
etl::tuple<Types...>>
ETL_CONSTEXPR14 bool operator==(const etl::expected< TValue, TError > &lhs, const etl::expected< TValue2, TError2 > &rhs)
Equivalence operators.
Definition expected.h:974
integral_constant
Definition type_traits_generator.h:871
bitset_ext
Definition absolute.h:38
T & get(array< T, MAXN > &a)
Definition array.h:1174
void swap(etl::array< T, SIZE > &lhs, etl::array< T, SIZE > &rhs)
Template deduction guides.
Definition array.h:1085
ETL_CONSTEXPR TContainer::size_type size(const TContainer &container)
Definition iterator.h:1187
ETL_NODISCARD ETL_CONSTEXPR14 T round_half_even_unscaled(T value) ETL_NOEXCEPT
Definition scaled_rounding.h:314
Definition tuple_size.h:38