Add type_list functionality to etl::variant using etl::variant_from_type_list

This commit is contained in:
John Wellbelove 2026-01-28 17:22:37 +00:00
parent d7dc1281ae
commit 69b741adb8
2 changed files with 64 additions and 58 deletions

View File

@ -253,7 +253,7 @@ namespace etl
template <size_t Index, typename... TTypes>
struct variant_alternative<Index, etl::variant<TTypes...>>
{
using type = etl::nth_type_t<Index, typename etl::variant<TTypes...>::type_list>;
using type = etl::nth_type_t<Index, TTypes...>;
};
template <size_t Index, typename T>
@ -1218,26 +1218,13 @@ namespace etl
size_t type_id;
};
//***************************************************************************
/// Delcare a variant using an etl::type_list.
//***************************************************************************
template <typename... TTypes>
class variant<etl::type_list<TTypes...>> : public etl::variant<TTypes...>
{
public:
using base_type = etl::variant<TTypes...>;
using type_list = typename base_type::type_list;
using base_type::base_type; // Inherit all ctors
};
//***************************************************************************
/// Checks if the variant v holds the alternative T.
//***************************************************************************
template <typename T, typename... TTypes>
ETL_CONSTEXPR14 bool holds_alternative(const etl::variant<TTypes...>& v) ETL_NOEXCEPT
{
constexpr size_t Index = etl::type_list_index_of_type<typename etl::variant<TTypes...>::type_list, T>::value;
constexpr size_t Index = etl::type_list_index_of_type<etl::type_list<TTypes...>, T>::value;
return (Index == variant_npos) ? false : (v.index() == Index);
}
@ -1268,7 +1255,7 @@ namespace etl
get(etl::variant<TTypes...>& v)
{
#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
static_assert(Index < etl::type_list_size<typename etl::variant<TTypes...>::type_list>::value, "Index out of range");
static_assert(Index < etl::type_list_size<etl::type_list<TTypes...>>::value, "Index out of range");
#endif
ETL_ASSERT(Index == v.index(), ETL_ERROR(etl::variant_incorrect_type_exception));
@ -1441,7 +1428,7 @@ namespace etl
template <typename... TTypes>
struct variant_size<etl::variant<TTypes...>>
: etl::integral_constant<size_t, etl::type_list_size<typename etl::variant<TTypes...>::type_list>::value>
: etl::integral_constant<size_t, etl::type_list_size<etl::type_list<TTypes...>>::value>
{
};
@ -1867,5 +1854,19 @@ namespace etl
}
}
#endif
//***************************************************************************
/// Helper to turn etl::type_list<TTypes...> into etl::variant<TTypes...>
template <typename TList>
struct variant_from_type_list;
template <typename... TTypes>
struct variant_from_type_list<etl::type_list<TTypes...>>
{
using type = etl::variant<TTypes...>;
};
template <typename TTypeList>
using variant_from_type_list_t = typename variant_from_type_list<TTypeList>::type;
}
#endif

View File

@ -427,10 +427,10 @@ namespace
{
TEST(test_alignment)
{
typedef etl::variant<char, unsigned char> test_variant_a;
typedef etl::variant<char, short> test_variant_b;
typedef etl::variant<char, int> test_variant_c;
typedef etl::variant<char, double> test_variant_d;
using test_variant_a = etl::variant<char, unsigned char>;
using test_variant_b = etl::variant<char, short>;
using test_variant_c = etl::variant<char, int>;
using test_variant_d = etl::variant<char, double>;
static test_variant_a a(char('1'));
static test_variant_b b(short(2));
@ -443,6 +443,48 @@ namespace
CHECK((uintptr_t(&etl::get<double>(d)) % uintptr_t(etl::alignment_of<double>::value)) == 0);
}
//*************************************************************************
TEST(test_variant_from_type_list)
{
struct DefaultConstructible
{
DefaultConstructible()
: value(1)
{
}
int value = 0;
};
using type_list = etl::type_list<DefaultConstructible, int, std::string>;
using test_variant_t = etl::variant_from_type_list_t<type_list>;
using normal_variant_t = etl::variant<DefaultConstructible, int, std::string>;
CHECK_NO_THROW(test_variant_t variant_etl);
test_variant_t variant_etl;
// Are the type lists the same?
CHECK_TRUE((std::is_same<test_variant_t::type_list, type_list>::value));
// Are the variants the same?
CHECK_TRUE((std::is_same<test_variant_t, normal_variant_t>::value));
CHECK_TRUE(etl::holds_alternative<DefaultConstructible>(variant_etl));
CHECK_FALSE(etl::holds_alternative<int>(variant_etl));
CHECK_FALSE(etl::holds_alternative<std::string>(variant_etl));
CHECK_EQUAL(1, etl::get<0U>(variant_etl).value);
CHECK_TRUE(etl::holds_alternative<0U>(variant_etl));
CHECK_FALSE(etl::holds_alternative<1U>(variant_etl));
CHECK_FALSE(etl::holds_alternative<2U>(variant_etl));
CHECK_TRUE(etl::holds_alternative(0U, variant_etl));
CHECK_FALSE(etl::holds_alternative(1U, variant_etl));
CHECK_FALSE(etl::holds_alternative(2U, variant_etl));
CHECK_FALSE(etl::holds_alternative(99U, variant_etl));
}
//*************************************************************************
TEST(test_constructor_default)
{
@ -479,43 +521,6 @@ namespace
CHECK_FALSE(etl::holds_alternative(99U, variant_etl));
}
//*************************************************************************
TEST(test_constructor_default_variant_from_type_list)
{
struct DefaultConstructible
{
DefaultConstructible()
: value(1)
{
}
int value = 0;
};
using variant_types = etl::type_list<DefaultConstructible, int, std::string>;
using test_variant_t = etl::variant<variant_types>;
CHECK_NO_THROW(test_variant_t variant_etl);
test_variant_t variant_etl;
CHECK_TRUE((std::is_same<test_variant_t::type_list, variant_types>::value));
CHECK_TRUE(etl::holds_alternative<DefaultConstructible>(variant_etl));
CHECK_FALSE(etl::holds_alternative<int>(variant_etl));
CHECK_FALSE(etl::holds_alternative<std::string>(variant_etl));
CHECK_EQUAL(1, etl::get<0U>(variant_etl).value);
CHECK_TRUE(etl::holds_alternative<0U>(variant_etl));
CHECK_FALSE(etl::holds_alternative<1U>(variant_etl));
CHECK_FALSE(etl::holds_alternative<2U>(variant_etl));
CHECK_TRUE(etl::holds_alternative(0U, variant_etl));
CHECK_FALSE(etl::holds_alternative(1U, variant_etl));
CHECK_FALSE(etl::holds_alternative(2U, variant_etl));
CHECK_FALSE(etl::holds_alternative(99U, variant_etl));
}
//*************************************************************************
TEST(test_constructor_value)
{