mirror of
https://github.com/ETLCPP/etl.git
synced 2026-11-09 14:49:53 +08:00
Fold expression experiment
This commit is contained in:
parent
f4060bc9ea
commit
67c19bb0dc
@ -7,7 +7,7 @@ Embedded Template Library.
|
|||||||
https://github.com/ETLCPP/etl
|
https://github.com/ETLCPP/etl
|
||||||
https://www.etlcpp.com
|
https://www.etlcpp.com
|
||||||
|
|
||||||
Copyright(c) 2014 jwellbelove
|
Copyright(c) 2021 jwellbelove
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -43,11 +43,56 @@ SOFTWARE.
|
|||||||
#include "../parameter_pack.h"
|
#include "../parameter_pack.h"
|
||||||
#include "../placement_new.h"
|
#include "../placement_new.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#if defined(ETL_COMPILER_KEIL)
|
#if defined(ETL_COMPILER_KEIL)
|
||||||
#pragma diag_suppress 940
|
#pragma diag_suppress 940
|
||||||
#pragma diag_suppress 111
|
#pragma diag_suppress 111
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace etl
|
||||||
|
{
|
||||||
|
//template <typename T, T... Integers>
|
||||||
|
//class integer_sequence
|
||||||
|
//{
|
||||||
|
//public:
|
||||||
|
//
|
||||||
|
// ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Integral types only");
|
||||||
|
|
||||||
|
// typedef T value_type;
|
||||||
|
//
|
||||||
|
// static ETL_CONSTEXPR size_t size() ETL_NOEXCEPT
|
||||||
|
// {
|
||||||
|
// return sizeof...(Integers);
|
||||||
|
// }
|
||||||
|
//};
|
||||||
|
|
||||||
|
//namespace private_integer_sequence
|
||||||
|
//{
|
||||||
|
// template <size_t N, typename IndexSeq>
|
||||||
|
// struct make_index_sequence;
|
||||||
|
|
||||||
|
// template <size_t N, size_t... Indices>
|
||||||
|
// struct make_index_sequence<N, integer_sequence<size_t, Indices...>>
|
||||||
|
// {
|
||||||
|
// typedef typename make_index_sequence<N - 1, integer_sequence<size_t, N - 1, Indices...>>::type type;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// template <size_t... Indices>
|
||||||
|
// struct make_index_sequence<0, integer_sequence<size_t, Indices...>>
|
||||||
|
// {
|
||||||
|
// typedef integer_sequence<size_t, Indices...> type;
|
||||||
|
// };
|
||||||
|
//}
|
||||||
|
|
||||||
|
//template <size_t N>
|
||||||
|
//using make_index_sequence = typename private_integer_sequence::make_index_sequence<N, integer_sequence<size_t>>::type;
|
||||||
|
|
||||||
|
//template <size_t... Indices>
|
||||||
|
//using index_sequence = integer_sequence<size_t, Indices...>;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
///\defgroup variant variant
|
///\defgroup variant variant
|
||||||
/// A class that can contain one a several specified types in a type safe manner.
|
/// A class that can contain one a several specified types in a type safe manner.
|
||||||
@ -68,6 +113,13 @@ namespace etl
|
|||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr bool operator >(etl::monostate, etl::monostate) noexcept { return false; }
|
||||||
|
constexpr bool operator <(etl::monostate, etl::monostate) noexcept { return false; }
|
||||||
|
constexpr bool operator !=(etl::monostate, etl::monostate) noexcept { return false; }
|
||||||
|
constexpr bool operator <=(etl::monostate, etl::monostate) noexcept { return true; }
|
||||||
|
constexpr bool operator >=(etl::monostate, etl::monostate) noexcept { return true; }
|
||||||
|
constexpr bool operator ==(etl::monostate, etl::monostate) noexcept { return true; }
|
||||||
|
|
||||||
//***************************************************************************
|
//***************************************************************************
|
||||||
/// Base exception for the variant class.
|
/// Base exception for the variant class.
|
||||||
///\ingroup variant
|
///\ingroup variant
|
||||||
@ -207,11 +259,11 @@ namespace etl
|
|||||||
{
|
{
|
||||||
static_assert(etl::is_one_of<T, TTypes...>::value, "Unsupported type");
|
static_assert(etl::is_one_of<T, TTypes...>::value, "Unsupported type");
|
||||||
|
|
||||||
T temp(etl::forward<TArgs>(args)...);
|
|
||||||
|
|
||||||
operation(action_type::Destruct, data, nullptr);
|
operation(action_type::Destruct, data, nullptr);
|
||||||
|
|
||||||
operation = do_operation<T>;
|
operation = do_operation<T>;
|
||||||
|
|
||||||
|
T temp(etl::forward<TArgs>(args)...);
|
||||||
operation(action_type::Construct, data, &temp);
|
operation(action_type::Construct, data, &temp);
|
||||||
|
|
||||||
type_id = etl::parameter_pack<TTypes...>::index_of_type<T>::value;
|
type_id = etl::parameter_pack<TTypes...>::index_of_type<T>::value;
|
||||||
@ -312,6 +364,15 @@ namespace etl
|
|||||||
return static_cast<const T&>(data);
|
return static_cast<const T&>(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//***************************************************************************
|
||||||
|
/// Do an operation determined by type.
|
||||||
|
//***************************************************************************
|
||||||
|
template <typename TVisitor>
|
||||||
|
void accept(TVisitor& visitor)
|
||||||
|
{
|
||||||
|
do_accept(visitor, std::make_index_sequence<sizeof...(TTypes)>{});
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
using operation_type = void(*)(action_type, void*, const void*);
|
using operation_type = void(*)(action_type, void*, const void*);
|
||||||
@ -343,6 +404,32 @@ namespace etl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//***************************************************************************
|
||||||
|
/// Loop through the types until a match is found.
|
||||||
|
//***************************************************************************
|
||||||
|
template <typename TVisitor, size_t... I>
|
||||||
|
void do_accept(TVisitor& visitor, std::index_sequence<I...>)
|
||||||
|
{
|
||||||
|
(attempt_visitor<I>(visitor) || ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
//***************************************************************************
|
||||||
|
/// Attempt to call a visitor.
|
||||||
|
//***************************************************************************
|
||||||
|
template <size_t Index, typename TVisitor>
|
||||||
|
bool attempt_visitor(TVisitor& visitor)
|
||||||
|
{
|
||||||
|
if (Index == index())
|
||||||
|
{
|
||||||
|
visitor.visit(etl::get<Index>(*this));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//***************************************************************************
|
//***************************************************************************
|
||||||
/// Default operation.
|
/// Default operation.
|
||||||
//***************************************************************************
|
//***************************************************************************
|
||||||
@ -401,7 +488,7 @@ namespace etl
|
|||||||
constexpr etl::variant_alternative_t<Index, etl::variant<TTypes...>>&
|
constexpr etl::variant_alternative_t<Index, etl::variant<TTypes...>>&
|
||||||
get(etl::variant<TTypes...>& v)
|
get(etl::variant<TTypes...>& v)
|
||||||
{
|
{
|
||||||
static_assert(Index < sizeof...(TTypes), "Index out of range");
|
//static_assert(Index < sizeof...(TTypes), "Index out of range");
|
||||||
ETL_ASSERT(Index == v.index(), ETL_ERROR(etl::variant_incorrect_type_exception));
|
ETL_ASSERT(Index == v.index(), ETL_ERROR(etl::variant_incorrect_type_exception));
|
||||||
|
|
||||||
using type = etl::variant_alternative_t<Index, etl::variant<TTypes...>>;
|
using type = etl::variant_alternative_t<Index, etl::variant<TTypes...>>;
|
||||||
@ -559,5 +646,4 @@ namespace etl
|
|||||||
: etl::integral_constant<size_t, variant_size<T>::value>
|
: etl::integral_constant<size_t, variant_size<T>::value>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@ Embedded Template Library.
|
|||||||
https://github.com/ETLCPP/etl
|
https://github.com/ETLCPP/etl
|
||||||
https://www.etlcpp.com
|
https://www.etlcpp.com
|
||||||
|
|
||||||
Copyright(c) 2014 jwellbelove
|
Copyright(c) 2021 jwellbelove
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -29,6 +29,7 @@ SOFTWARE.
|
|||||||
#include "unit_test_framework.h"
|
#include "unit_test_framework.h"
|
||||||
|
|
||||||
#include "etl/private/variant_new.h"
|
#include "etl/private/variant_new.h"
|
||||||
|
#include "etl/visitor.h"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -395,5 +396,40 @@ namespace
|
|||||||
|
|
||||||
D1 db = etl::move(etl::get<D1>(variant));
|
D1 db = etl::move(etl::get<D1>(variant));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//*************************************************************************
|
||||||
|
TEST(test_variant_visitor)
|
||||||
|
{
|
||||||
|
struct Visitor : public etl::visitor<char, int, std::string>
|
||||||
|
{
|
||||||
|
void visit(char& c)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void visit(int& i)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void visit(std::string& s)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Visitor visitor;
|
||||||
|
|
||||||
|
test_variant_3 variant;
|
||||||
|
|
||||||
|
variant = char(1);
|
||||||
|
variant.accept(visitor);
|
||||||
|
|
||||||
|
variant = int(2);
|
||||||
|
variant.accept(visitor);
|
||||||
|
|
||||||
|
variant = std::string("3");
|
||||||
|
variant.accept(visitor);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user