etl::variant release candidate

This commit is contained in:
John Wellbelove 2021-07-17 23:45:28 +01:00
parent 7b63b567b6
commit aa98a60822
7 changed files with 197 additions and 220 deletions

View File

@ -65,44 +65,6 @@ namespace etl
#else
//*************************************************************************
/// Variadic template definition of overload for C++14.
//*************************************************************************
//namespace private_overload
//{
// //***********************************
// // Overload helper templates.
// //***********************************
// template <typename... TOverloads>
// struct overload_helper;
// template <>
// struct overload_helper<>
// {
// };
// template <typename TFirst, typename... TOthers>
// struct overload_helper<TFirst, TOthers...> : TFirst, overload_helper<TOthers...>
// {
// using TFirst::operator();
// template <typename UFirst, typename... UOthers>
// overload_helper(UFirst&& u, UOthers&&... others)
// : TFirst{ etl::forward<UFirst>(u) }, overload_helper<TOthers...>{ etl::forward<UOthers>(others)... }
// {
// }
// };
//}
////***********************************
///// Make an overload.
////***********************************
//template <typename... TOverloads>
//constexpr auto make_overload(TOverloads&&... overloads)
//{
// return private_overload::overload_helper<TOverloads...>{ etl::forward<TOverloads>(overloads)... };
//}
template <typename TFirst, typename... TOthers>
struct overload : TFirst, overload<TOthers...>
{
@ -110,7 +72,8 @@ namespace etl
using overload<TOthers...>::operator();
};
template <typename TFirst> struct overload<TFirst> : TFirst
template <typename TFirst>
struct overload<TFirst> : TFirst
{
using TFirst::operator();
};

View File

@ -940,18 +940,18 @@ namespace etl
void do_operator(TVisitor& visitor)
{
#if defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
ETL_STATIC_ASSERT(sizeof...(TTypes) <= 8U, "There are more than 8 types in this variant");
ETL_STATIC_ASSERT(sizeof...(TTypes) <= 8U, "ETL_VARIANT_CPP11_MAX_8_TYPES - Only a maximum of 8 types are allowed in this variant");
#endif
#if defined(ETL_VARIANT_CPP11_MAX_16_TYPES)
ETL_STATIC_ASSERT(sizeof...(TTypes) <= 16U, "There are more than 16 types in this variant");
ETL_STATIC_ASSERT(sizeof...(TTypes) <= 16U, "ETL_VARIANT_CPP11_MAX_16_TYPES - Only a maximum of 16 types are allowed in this variant");
#endif
#if defined(ETL_VARIANT_CPP11_MAX_24_TYPES)
ETL_STATIC_ASSERT(sizeof...(TTypes) <= 24U, "There are more than 24 types in this variant");
ETL_STATIC_ASSERT(sizeof...(TTypes) <= 24U, "ETL_VARIANT_CPP11_MAX_24_TYPES - Only a maximum of 24 types are allowed in this variant");
#endif
ETL_STATIC_ASSERT(sizeof...(TTypes) <= 32U, "There are more than 32 types in this variant");
ETL_STATIC_ASSERT(sizeof...(TTypes) <= 32U, "A maximum of 32 types are allowed in this variant");
switch (index())
{
@ -1162,9 +1162,9 @@ namespace etl
}
//***************************************************************************
/// get_if (pointer parameter)
//***************************************************************************
template < size_t Index, typename... TTypes >
/// get_if
//***************************************************************************
template< size_t Index, typename... TTypes >
ETL_CONSTEXPR14 etl::add_pointer_t<etl::variant_alternative_t<Index, etl::variant<TTypes...>>>
get_if(etl::variant<TTypes...>* pv) noexcept
{
@ -1199,7 +1199,14 @@ namespace etl
{
constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
return etl::get_if<Index>(pv);
if ((pv != nullptr) && (pv->index() == Index))
{
return &etl::get<Index>(*pv);
}
else
{
return nullptr;
}
}
//***********************************
@ -1208,19 +1215,9 @@ namespace etl
{
constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
return etl::get_if<Index>(pv);
}
//***************************************************************************
/// get_if (reference parameter)
//***************************************************************************
template < size_t Index, typename... TTypes >
ETL_CONSTEXPR14 etl::add_pointer_t<etl::variant_alternative_t<Index, etl::variant<TTypes...>>>
get_if(etl::variant<TTypes...>& v) noexcept
{
if (v.index() == Index)
if ((pv != nullptr) && (pv->index() == Index))
{
return &etl::get<Index>(v);
return &etl::get<Index>(*pv);
}
else
{
@ -1228,63 +1225,6 @@ namespace etl
}
}
//***********************************
template< size_t Index, typename... TTypes >
ETL_CONSTEXPR14 etl::add_pointer_t<const etl::variant_alternative_t<Index, etl::variant<TTypes...>>>
get_if(const etl::variant<TTypes...>& v) noexcept
{
if (v.index() == Index)
{
return &etl::get<Index>(v);
}
else
{
return nullptr;
}
}
//***********************************
template< size_t Index, typename... TTypes >
ETL_CONSTEXPR14 etl::add_pointer_t<const etl::variant_alternative_t<Index, etl::variant<TTypes...>>>
get_if(etl::variant<TTypes...>&& v) noexcept
{
if (v.index() == Index)
{
return &etl::get<Index>(v);
}
else
{
return nullptr;
}
}
//***********************************
template< class T, typename... TTypes >
ETL_CONSTEXPR14 etl::add_pointer_t<T> get_if(etl::variant<TTypes...>& v) noexcept
{
constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
return etl::get_if<Index>(v);
}
//***********************************
template< class T, typename... TTypes >
ETL_CONSTEXPR14 etl::add_pointer_t<const T> get_if(const etl::variant<TTypes...>& v) noexcept
{
constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
return etl::get_if<Index>(v);
}
//***********************************
template< class T, typename... TTypes >
ETL_CONSTEXPR14 etl::add_pointer_t<const T> get_if(etl::variant<TTypes...>&& v) noexcept
{
constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
return etl::get_if<Index>(v);
}
//***************************************************************************
/// swap
//***************************************************************************

View File

@ -31,7 +31,7 @@ SOFTWARE.
#ifndef ETL_VARIANT_INCLUDED
#define ETL_VARIANT_INCLUDED
#if ETL_USE_LEGACY_VARIANT
#if !ETL_CPP11_SUPPORTED || ETL_USE_LEGACY_VARIANT
#include "private/variant_legacy.h"
#else
#include "private/variant_new.h"

View File

@ -100,7 +100,7 @@ SOFTWARE.
#define ETL_MEM_CAST_FORCE_CPP03
#endif
#define ETL_OVERLOAD_FORCE_CPP14
//#define ETL_OVERLOAD_FORCE_CPP14
//#define ETL_VARIANT_FORCE_CPP11
#define ETL_VARIANT_CPP11_MAX_16_TYPES

View File

@ -68,9 +68,7 @@ namespace
using MemCast = etl::mem_cast<Size, Alignment>;
using MemCastTypes = etl::mem_cast_types<char, double, Data>;
char c;
double d;
Data data;
Data data;
SUITE(test_mem_cast)
{

View File

@ -65,8 +65,6 @@ namespace
// Test variant types.
using MemCast = etl::mem_cast_ptr;
char c;
double d;
Data data;
char* Ptr(int i)
@ -83,8 +81,6 @@ namespace
{
MemCast memCast;
char* p = nullptr;
memCast.data(Ptr(1));
CHECK_EQUAL(1U , memCast.alignment());

View File

@ -30,6 +30,7 @@ SOFTWARE.
#include "etl/private/variant_new.h"
#include "etl/visitor.h"
#include "etl/overload.h"
#include <array>
#include <vector>
@ -675,7 +676,7 @@ namespace
}
//*************************************************************************
TEST(test_variant_visitor)
TEST(test_variant_accept_visitor)
{
struct Visitor : public etl::visitor<char, int, std::string>
{
@ -724,7 +725,7 @@ namespace
}
//*************************************************************************
TEST(test_variant_operator_visit)
TEST(test_variant_accept_functor_with_functor_class)
{
struct Visitor
{
@ -745,7 +746,7 @@ namespace
result_i = i;
}
void operator()(std::string& s)
void operator()(const std::string& s)
{
result_s = s;
}
@ -772,6 +773,35 @@ namespace
CHECK_EQUAL("3", visitor.result_s);
}
//*************************************************************************
TEST(test_variant__accept_functor_with_overload)
{
char result_c;
int result_i;
std::string result_s;
auto visitor = etl::overload
{
[&result_c](char c) { result_c = 1; },
[&result_i](int i) { result_i = 2; },
[&result_s](const std::string& s) { result_s = "3"; }
};
test_variant_etl_3 variant_etl;
variant_etl = char(1);
variant_etl.accept_functor(visitor);
CHECK_EQUAL(1, result_c);
variant_etl = int(2);
variant_etl.accept_functor(visitor);
CHECK_EQUAL(2, result_i);
variant_etl = std::string("3");
variant_etl.accept_functor(visitor);
CHECK_EQUAL("3", result_s);
}
//*************************************************************************
TEST(test_get_if_index)
{
@ -779,27 +809,18 @@ namespace
variant_etl = char(1);
CHECK(etl::get_if<0>(&variant_etl) != nullptr);
CHECK(etl::get_if<0>(variant_etl) != nullptr);
CHECK(etl::get_if<1>(&variant_etl) == nullptr);
CHECK(etl::get_if<1>(variant_etl) == nullptr);
CHECK(etl::get_if<2>(&variant_etl) == nullptr);
CHECK(etl::get_if<2>(variant_etl) == nullptr);
variant_etl = int(2);
CHECK(etl::get_if<0>(&variant_etl) == nullptr);
CHECK(etl::get_if<0>(variant_etl) == nullptr);
CHECK(etl::get_if<1>(&variant_etl) != nullptr);
CHECK(etl::get_if<1>(variant_etl) != nullptr);
CHECK(etl::get_if<2>(&variant_etl) == nullptr);
CHECK(etl::get_if<2>(variant_etl) == nullptr);
variant_etl = std::string("3");
CHECK(etl::get_if<0>(&variant_etl) == nullptr);
CHECK(etl::get_if<0>(variant_etl) == nullptr);
CHECK(etl::get_if<1>(&variant_etl) == nullptr);
CHECK(etl::get_if<1>(variant_etl) == nullptr);
CHECK(etl::get_if<2>(&variant_etl) != nullptr);
CHECK(etl::get_if<2>(variant_etl) != nullptr);
}
//*************************************************************************
@ -809,27 +830,18 @@ namespace
variant_etl = char(1);
CHECK(etl::get_if<char>(&variant_etl) != nullptr);
CHECK(etl::get_if<char>(variant_etl) != nullptr);
CHECK(etl::get_if<int>(&variant_etl) == nullptr);
CHECK(etl::get_if<int>(variant_etl) == nullptr);
CHECK(etl::get_if<std::string>(&variant_etl) == nullptr);
CHECK(etl::get_if<std::string>(variant_etl) == nullptr);
variant_etl = int(2);
CHECK(etl::get_if<char>(&variant_etl) == nullptr);
CHECK(etl::get_if<char>(variant_etl) == nullptr);
CHECK(etl::get_if<int>(&variant_etl) != nullptr);
CHECK(etl::get_if<int>(variant_etl) != nullptr);
CHECK(etl::get_if<std::string>(&variant_etl) == nullptr);
CHECK(etl::get_if<std::string>(variant_etl) == nullptr);
variant_etl = std::string("3");
CHECK(etl::get_if<char>(&variant_etl) == nullptr);
CHECK(etl::get_if<char>(variant_etl) == nullptr);
CHECK(etl::get_if<int>(&variant_etl) == nullptr);
CHECK(etl::get_if<int>(variant_etl) == nullptr);
CHECK(etl::get_if<std::string>(&variant_etl) != nullptr);
CHECK(etl::get_if<std::string>(variant_etl) != nullptr);
}
//*************************************************************************
@ -938,97 +950,165 @@ namespace
//*************************************************************************
TEST(test_get_by_type)
{
MoveableCopyable movecopyable;
MoveableCopyable value1;
MoveableCopyable value2;
MoveableCopyable value3;
etl::variant<MoveableCopyable> v(movecopyable);
etl::variant<MoveableCopyable> v_etl(value1);
const etl::variant<MoveableCopyable> cv_etl(value2);
etl::variant<MoveableCopyable>& rv_etl(v_etl);
const etl::variant<MoveableCopyable>& crv_etl(value3);
const etl::variant<MoveableCopyable> cv(movecopyable);
etl::variant<MoveableCopyable>& rv(v);
const etl::variant<MoveableCopyable>& crv(v);
std::variant<MoveableCopyable> v_std(value1);
const std::variant<MoveableCopyable> cv_std(value2);
std::variant<MoveableCopyable>& rv_std(v_std);
const std::variant<MoveableCopyable>& crv_std(value3);
// From variant reference
MoveableCopyable movecopyable_vr = etl::get<MoveableCopyable>(rv);
// From variant rvalue reference
MoveableCopyable&& movecopyable_vrr = etl::get<MoveableCopyable>(etl::move(v));
MoveableCopyable value_vr_etl = etl::get<MoveableCopyable>(rv_etl);
MoveableCopyable value_vr_std = std::get<MoveableCopyable>(rv_std);
CHECK_EQUAL(value_vr_std.moved_from, value_vr_etl.moved_from);
CHECK_EQUAL(value_vr_std.moved_to, value_vr_etl.moved_to);
CHECK_EQUAL(value_vr_std.copied_to, value_vr_etl.copied_to);
// From variant const reference
const MoveableCopyable& movecopyable_vcr = etl::get<MoveableCopyable>(crv);
const MoveableCopyable& value_vcr_etl = etl::get<MoveableCopyable>(crv_etl);
const MoveableCopyable& value_vcr_std = std::get<MoveableCopyable>(crv_std);
CHECK_EQUAL(value_vcr_std.moved_from, value_vcr_etl.moved_from);
CHECK_EQUAL(value_vcr_std.moved_to, value_vcr_etl.moved_to);
CHECK_EQUAL(value_vcr_std.copied_to, value_vcr_etl.copied_to);
// From variant rvalue reference
MoveableCopyable&& value_vrr_etl = etl::get<MoveableCopyable>(etl::move(v_etl));
MoveableCopyable&& value_vrr_std = std::get<MoveableCopyable>(etl::move(v_std));
CHECK_EQUAL(value_vrr_std.moved_from, value_vrr_etl.moved_from);
CHECK_EQUAL(value_vrr_std.moved_to, value_vrr_etl.moved_to);
CHECK_EQUAL(value_vrr_std.copied_to, value_vrr_etl.copied_to);
// From variant const rvalue reference
const MoveableCopyable&& movecopyable_vcrr = etl::get<MoveableCopyable>(etl::move(cv));
const MoveableCopyable&& value_vcrr_etl = etl::get<MoveableCopyable>(etl::move(cv_etl));
const MoveableCopyable&& value_vcrr_std = std::get<MoveableCopyable>(etl::move(cv_std));
CHECK_EQUAL(value_vcrr_std.moved_from, value_vcrr_etl.moved_from);
CHECK_EQUAL(value_vcrr_std.moved_to, value_vcrr_etl.moved_to);
CHECK_EQUAL(value_vcrr_std.copied_to, value_vcrr_etl.copied_to);
}
//*************************************************************************
//TEST(test_copyable_vs_moveable_types_etl)
//{
// Copyable copyable_from;
// Copyable copyable_to;
TEST(test_get_by_index)
{
MoveableCopyable value1;
MoveableCopyable value2;
MoveableCopyable value3;
// Moveable moveable_from;
// Moveable moveable_to;
etl::variant<MoveableCopyable> v_etl(value1);
const etl::variant<MoveableCopyable> cv_etl(value2);
etl::variant<MoveableCopyable>& rv_etl(v_etl);
const etl::variant<MoveableCopyable>& crv_etl(value3);
// MoveableCopyable movecopyable_from1;
// MoveableCopyable movecopyable_from2;
// MoveableCopyable movecopyable_to1;
// MoveableCopyable movecopyable_to2;
std::variant<MoveableCopyable> v_std(value1);
const std::variant<MoveableCopyable> cv_std(value2);
std::variant<MoveableCopyable>& rv_std(v_std);
const std::variant<MoveableCopyable>& crv_std(value3);
// etl::variant<Copyable> variant_c(copyable_from);
// copyable_to = etl::get<0>(variant_c);
// From variant reference
MoveableCopyable value_vr_etl = etl::get<0U>(rv_etl);
MoveableCopyable value_vr_std = std::get<0U>(rv_std);
CHECK_EQUAL(value_vr_std.moved_from, value_vr_etl.moved_from);
CHECK_EQUAL(value_vr_std.moved_to, value_vr_etl.moved_to);
CHECK_EQUAL(value_vr_std.copied_to, value_vr_etl.copied_to);
// etl::variant<Moveable> variant_m(etl::move(moveable_from));
// moveable_to = etl::move(etl::get<0>(variant_m));
// From variant const reference
const MoveableCopyable& value_vcr_etl = etl::get<0U>(crv_etl);
const MoveableCopyable& value_vcr_std = std::get<0U>(crv_std);
CHECK_EQUAL(value_vcr_std.moved_from, value_vcr_etl.moved_from);
CHECK_EQUAL(value_vcr_std.moved_to, value_vcr_etl.moved_to);
CHECK_EQUAL(value_vcr_std.copied_to, value_vcr_etl.copied_to);
// etl::variant<MoveableCopyable> variant_mc1(movecopyable_from1);
// movecopyable_to1 = etl::get<0>(variant_mc1);
// From variant rvalue reference
MoveableCopyable&& value_vrr_etl = etl::get<0U>(etl::move(v_etl));
MoveableCopyable&& value_vrr_std = std::get<0U>(etl::move(v_std));
CHECK_EQUAL(value_vrr_std.moved_from, value_vrr_etl.moved_from);
CHECK_EQUAL(value_vrr_std.moved_to, value_vrr_etl.moved_to);
CHECK_EQUAL(value_vrr_std.copied_to, value_vrr_etl.copied_to);
// etl::variant<MoveableCopyable> variant_mc2(etl::move(movecopyable_from2));
// movecopyable_to2 = etl::move(etl::get<0>(variant_mc2));
// etl::variant<MoveableCopyable> variant_mc3(variant_mc1);
// etl::variant<MoveableCopyable> variant_mc4(etl::move(variant_mc1));
// etl::variant<MoveableCopyable> variant_mc5(variant_mc2);
// etl::variant<MoveableCopyable> variant_mc6(etl::move(variant_mc2));
//}
// From variant const rvalue reference
const MoveableCopyable&& value_vcrr_etl = etl::get<0U>(etl::move(cv_etl));
const MoveableCopyable&& value_vcrr_std = std::get<0U>(etl::move(cv_std));
CHECK_EQUAL(value_vcrr_std.moved_from, value_vcrr_etl.moved_from);
CHECK_EQUAL(value_vcrr_std.moved_to, value_vcrr_etl.moved_to);
CHECK_EQUAL(value_vcrr_std.copied_to, value_vcrr_etl.copied_to);
}
//*************************************************************************
// TEST(test_copyable_vs_moveable_types_std)
// {
// Copyable copyable_from;
// Copyable copyable_to;
//
// Moveable moveable_from;
// Moveable moveable_to;
//
// MoveableCopyable movecopyable_from1;
// MoveableCopyable movecopyable_from2;
// MoveableCopyable movecopyable_to1;
// MoveableCopyable movecopyable_to2;
//
// std::variant<Copyable> variant_c(copyable_from);
// copyable_to = std::get<0>(variant_c);
//
// //std::variant<Moveable> variant_m(etl::move(moveable_from));
// //moveable_to = std::move(std::get<0>(variant_m));
//
// std::variant<MoveableCopyable> variant_mc1(movecopyable_from1);
// movecopyable_to1 = std::get<0>(variant_mc1);
//
//// std::variant<MoveableCopyable> variant_mc2(std::move(movecopyable_from2));
//// movecopyable_to2 = std::move(std::get<0>(variant_mc2));
//
//// std::variant<MoveableCopyable> variant_mc3(variant_mc1);
//
//// std::variant<MoveableCopyable> variant_mc4(std::move(variant_mc1));
//
//// std::variant<MoveableCopyable> variant_mc5(variant_mc2);
//
//// std::variant<MoveableCopyable> variant_mc6(std::move(variant_mc2));
// }
TEST(test_get_if_by_type)
{
int value;
etl::variant<int, double> v(value);
const etl::variant<int, double> cv(value);
etl::variant<int, double>& rv(v);
const etl::variant<int, double>& crv(v);
int* pi;
const int* pci;
double* pd;
const double* pcd;
etl::variant<int, double>* pv = nullptr;
// From nullptr
pi = etl::get_if<int>(pv);
CHECK(pi == nullptr);
// From variant reference
pi = etl::get_if<int>(&rv);
CHECK(pi != nullptr);
pd = etl::get_if<double>(&rv);
CHECK(pd == nullptr);
// From variant const reference
pci = etl::get_if<int>(&crv);
CHECK(pci != nullptr);
pcd = etl::get_if<double>(&crv);
CHECK(pcd == nullptr);
}
//*************************************************************************
TEST(test_get_if_by_index)
{
int value;
etl::variant<int, double> v(value);
const etl::variant<int, double> cv(value);
etl::variant<int, double>& rv(v);
const etl::variant<int, double>& crv(v);
int* pi;
const int* pci;
double* pd;
const double* pcd;
etl::variant<int, double>* pv = nullptr;
// From nullptr
pi = etl::get_if<0U>(pv);
CHECK(pi == nullptr);
// From variant reference
pi = etl::get_if<0U>(&rv);
CHECK(pi != nullptr);
pd = etl::get_if<1U>(&rv);
CHECK(pd == nullptr);
// From variant const reference
pci = etl::get_if<0U>(&crv);
CHECK(pci != nullptr);
pcd = etl::get_if<1U>(&crv);
CHECK(pcd == nullptr);
}
};
}