Add etl::type_list API to more classes. (#1275)

* Remove AppVeyor build status badge

Removed AppVeyor build status badge from README.

* Update README.md

* Update CONTRIBUTING.md

Updated the instructions for contributing.

* Added etl::type_list to etl::observer

* Added etl::type_list to etl::nth_type

* Added missing 'typename' to type_list nth_type

* Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277)

* Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Added type_list definitions for nth_type and observer

* Added etl::type_list to etl::variant

* Updated comments

* Addedetl::type~_list to message_router, observer, visitor

# Conflicts:
#	include/etl/observer.h
#	test/vs2022/etl.vcxproj.filters

* Added member type_list type to tuple

* Work in progress

* Copy changes from other source

* Removed unused tests

* Fix iter_swap namespace

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

* Add type_list functionality to etl::message_packet using etl::message_packet_from_type_list

* Add type_list functionality to etl::message_router using etl::message_router_from_type_list

* Add type_list functionality to etl::observer using etl::observer_from_type_list

* Add type_list functionality to etl::tuple using etl::tuple_from_type_list

* Allow etl::make_index_sequence to be created from an etl::type_list

* Add type_list functionality to etl::visitor using etl::visitor_from_type_list

* Fix iter_swap namespace

* Allow creation of a message_packet with no message types

* Allow creation of a message_router with no message types

* Updated VS2022 project files

* Added missing test files CMakeLists.txt

* Fix C++03 compatibility

Fixed unused aregument warnings

* Synced message_packet generator to updated code

* Synced message_router generator to updated code

* Synced message_router generator to updated code

# Conflicts:
#	include/etl/generators/message_router_generator.h
#	include/etl/message_router.h

* Fixed missing zero message specialisation for <= C++14

* Fixed missing zero message specialisation for <= C++14

* Fix year_month arithmetic and correct chrono API behavior (#1257)

* Fix & add more tests for year_month arithmetic

* Minor addtions to previous commit

* More missing values to be uninitialized

* Update the default constructors to = default and correct default constructor tests accordingly

* Fix & add more tests for year_month arithmetic

* Minor addtions to previous commit

* More missing values to be uninitialized

* Update the default constructors to = default and correct default constructor tests accordingly

* Restore default constructor behavior for chrono calender

* Suppress warnings from std in optimized builds (#1259)

When testing with ./run-tests.sh 23 3 10, some warnings from
std surfaced which resulted in build errors.

* Add template deduction guide for span from vector (#1264)

* Create span from vector deduction

* Use ivector for deduction.  Add vector_ext to test

* Add vector pointer to test

* Finish tests

* Initialize pdata_ext and others

* Document how to implement platform specifics (#1262)

Some interfaces need to be implemented in every project
or platform using the ETL:

* etl_get_high_resolution_clock
* etl_get_system_clock
* etl_get_steady_clock
* etl_putchar

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>

* Fix etl::as_bytes for etl::span<const T> (#1266)

A missing 'const' in the etl::as_bytes implementation was causing a
compile-time error when etl::as_bytes was called on a span of const
values.

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>

* Remove some UB in test_vector_non_trivial.cpp (#1268)

Some of the tests' UB are detectable by Gcc15 and thus give a compile error due to warnings-as-error flag.

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>

* Update C++26 deprecated constructs to ensure future standard compliance (#1267)

* Update C++26 deprecated constructs to ensure future standard compliance

I replaced std::is_trivial with a combination of std::is_trivially_default_constructible and std::is_trivially_copyable. Additionally, I added the required comma before the ellipsis in variadic functions to match updated language specifications.

* Some additional is_trivial related changes not found directly when compiling tests in C++26

---------

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>

* Fix return value of get_token_list (#1271)

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>

* Fix etl::tuple template signature error in pair assignment operator (#1265)

* Fix etl::tuple template signature error in pair assignment operator

* Remove AppVeyor build status badge

Removed AppVeyor build status badge from README.

* Update README.md

* Update etl::tuple to explicitly use etl::pair or std::pair in assignment operator

* Added tests for etl::tuple assignment from pair

---------

Co-authored-by: Bryton Flecker <bflecker@swe.com>
Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>

* Remove advance() on static spans (#1281)

* Remove AppVeyor build status badge

Removed AppVeyor build status badge from README.

* Update README.md

* Update CONTRIBUTING.md

Updated the instructions for contributing.

* Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277)

* Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Remove advance() on static spans

Since the size of a static span is constant, we can't reasonably
advance() on it.

---------

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>
Co-authored-by: Sergei <sergej.shirokov@gmail.com>

* Add missing includes (#1286)

* Remove AppVeyor build status badge

Removed AppVeyor build status badge from README.

* Update README.md

* Update CONTRIBUTING.md

Updated the instructions for contributing.

* Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277)

* Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Add missing includes

Before this change, the includes needed to be done explicitly by
files using basic_string_stream.h, and be included first. This
was error prone, especially if includes are reordered (e.g. via
the currently defined clang-format rules).

---------

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>
Co-authored-by: Sergei <sergej.shirokov@gmail.com>

* Move comparison operators of etl::expected to namespace etl (#1287)

* Remove AppVeyor build status badge

Removed AppVeyor build status badge from README.

* Update README.md

* Update CONTRIBUTING.md

Updated the instructions for contributing.

* Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277)

* Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Move comparison operators of etl::expected to namespace etl

---------

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>
Co-authored-by: Sergei <sergej.shirokov@gmail.com>

* Make typed_storage constructor constexpr (#1291)

* Remove AppVeyor build status badge

Removed AppVeyor build status badge from README.

* Update README.md

* Update CONTRIBUTING.md

Updated the instructions for contributing.

* Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277)

* Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Make typed_storage constructor constexpr

---------

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>
Co-authored-by: Sergei <sergej.shirokov@gmail.com>

* Add basic_format_arg constructor for ibasic_string (#1288)

* Allow string as format arg

* Remove AppVeyor build status badge

Removed AppVeyor build status badge from README.

* Update README.md

* Update CONTRIBUTING.md

Updated the instructions for contributing.

* Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277)

* Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Added test string escaped

* Add temporary string test

---------

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>
Co-authored-by: Sergei <sergej.shirokov@gmail.com>

* QR Code for Github

* Added etl::visitor_from_type_list

* accepts(id) for empty router passes on to a sucessor

* Fixed incorrect comment from 'tuple' to 'message_router'

* PR review changes

* PR review changes

* Fixed internal constexptr flag in message_packet

* Fixed unused variable in unti test

---------

Co-authored-by: John Wellbelove <john.wellbelove@etlcpp.co.uk>
Co-authored-by: Sergei <sergej.shirokov@gmail.com>
Co-authored-by: John Wellbelove <john.wellbelove@etlcpp.com>
Co-authored-by: Bo Rydberg <2945606+bolry@users.noreply.github.com>
Co-authored-by: Roland Reichwein <Roland.Reichwein@bmw.de>
Co-authored-by: Mike Bloom <91038685+mike919192@users.noreply.github.com>
Co-authored-by: taltenbach <92919739+taltenbach@users.noreply.github.com>
Co-authored-by: Bryton Flecker <fleckerbr@gmail.com>
Co-authored-by: Bryton Flecker <bflecker@swe.com>
This commit is contained in:
John Wellbelove 2026-02-19 12:41:48 +00:00 committed by GitHub
parent 1b244ec4c0
commit 226117b972
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 1452 additions and 61 deletions

View File

@ -71,6 +71,7 @@ cog.outl("//********************************************************************
#include "largest.h"
#include "alignment.h"
#include "utility.h"
#include "type_list.h"
#include <stdint.h>
@ -87,19 +88,21 @@ namespace etl
private:
template <typename T>
static constexpr bool IsMessagePacket = etl::is_same_v< etl::remove_const_t<etl::remove_reference_t<T>>, etl::message_packet<TMessageTypes...>>;
static constexpr bool IsMessagePacket = etl::is_same_v<etl::remove_const_t<etl::remove_reference_t<T>>, etl::message_packet<TMessageTypes...>>;
template <typename T>
static constexpr bool IsInMessageList = etl::is_one_of_v<etl::remove_const_t<etl::remove_reference_t<T>>, TMessageTypes...>;
template <typename T>
static constexpr bool IsIMessage = etl::is_same_v<remove_const_t<etl::remove_reference_t<T>>, etl::imessage>;
static constexpr bool IsIMessage = etl::is_same_v<etl::remove_const_t<etl::remove_reference_t<T>>, etl::imessage>;
public:
using message_types = etl::type_list<TMessageTypes...>;
//********************************************
#include "private/diagnostic_uninitialized_push.h"
message_packet()
constexpr message_packet() noexcept
: valid(false)
{
}
@ -260,7 +263,7 @@ namespace etl
//**********************************************
template <typename TMessage>
static ETL_CONSTEXPR
typename etl::enable_if<etl::is_base_of<etl::imessage, TMessage>::value, bool>::type
typename etl::enable_if<etl::is_base_of<etl::imessage, TMessage>::value, bool>::type
accepts()
{
return accepts<TMessage::ID>();
@ -392,6 +395,132 @@ namespace etl
bool valid;
};
//***************************************************************************
// The definition for no message types.
//***************************************************************************
template <>
class message_packet<>
{
private:
template <typename T>
static constexpr bool IsMessagePacket = etl::is_same_v<etl::remove_const_t<etl::remove_reference_t<T>>, etl::message_packet<>>;
template <typename T>
static constexpr bool IsInMessageList = false;
template <typename T>
static constexpr bool IsIMessage = etl::is_same_v<etl::remove_const_t<etl::remove_reference_t<T>>, etl::imessage>;
public:
using message_types = etl::type_list<>;
//********************************************
#include "private/diagnostic_uninitialized_push.h"
constexpr message_packet() noexcept
{
}
#include "private/diagnostic_pop.h"
//**********************************************
message_packet(const message_packet& /*other*/)
{
}
#if ETL_USING_CPP11
//**********************************************
message_packet(message_packet&& /*other*/)
{
}
#endif
//**********************************************
void copy(const message_packet& /*other*/)
{
}
//**********************************************
void copy(message_packet&& /*other*/)
{
}
//**********************************************
#include "private/diagnostic_uninitialized_push.h"
message_packet& operator =(const message_packet& /*rhs*/)
{
return *this;
}
#include "private/diagnostic_pop.h"
//**********************************************
#include "private/diagnostic_uninitialized_push.h"
message_packet& operator =(message_packet&& /*rhs*/)
{
return *this;
}
#include "private/diagnostic_pop.h"
//********************************************
~message_packet()
{
}
//********************************************
bool is_valid() const
{
return false;
}
//**********************************************
static ETL_CONSTEXPR bool accepts(etl::message_id_t /*id*/)
{
return false;
}
//**********************************************
static ETL_CONSTEXPR bool accepts(const etl::imessage& /*msg*/)
{
return false;
}
//**********************************************
template <etl::message_id_t Id>
static ETL_CONSTEXPR bool accepts()
{
return false;
}
//**********************************************
template <typename TMessage>
static ETL_CONSTEXPR
typename etl::enable_if<etl::is_base_of<etl::imessage, TMessage>::value, bool>::type
accepts()
{
return false;
}
enum
{
SIZE = 0,
ALIGNMENT = 1
};
};
//***************************************************************************
/// Helper to turn etl::type_list<TTypes...> into etl::message_packet<TTypes...>
template <typename TList>
struct message_packet_from_type_list;
template <typename... TTypes>
struct message_packet_from_type_list<etl::type_list<TTypes...>>
{
using type = etl::message_packet<TTypes...>;
};
template <typename TTypeList>
using message_packet_from_type_list_t = typename message_packet_from_type_list<TTypeList>::type;
#else
/*[[[cog
@ -470,8 +599,7 @@ namespace etl
cog.outl("// The definition for all %s message types." % Handlers)
cog.outl("//***************************************************************************")
cog.out("template <")
cog.out("typename T1, ")
for n in range(2, int(Handlers)):
for n in range(1, int(Handlers)):
cog.out("typename T%s = void, " % n)
if n % 4 == 0:
cog.outl("")
@ -481,9 +609,18 @@ namespace etl
cog.outl("{")
cog.outl("public:")
cog.outl("")
cog.outl("#if ETL_USING_CPP11")
cog.out(" using message_types = etl::type_list<")
for n in range(1, int(Handlers)):
cog.out("T%s, " % n)
cog.outl("T%s>;" % int(Handlers))
cog.outl("#endif")
cog.outl("")
cog.outl(" //********************************************")
cog.outl("#include \"private/diagnostic_uninitialized_push.h\"")
cog.outl(" message_packet()")
cog.outl(" ETL_CONSTEXPR message_packet() ETL_NOEXCEPT")
cog.outl(" : valid(false)")
cog.outl(" {")
cog.outl(" }")
@ -785,9 +922,19 @@ namespace etl
cog.outl("{")
cog.outl("public:")
cog.outl("")
cog.out("#if ETL_USING_CPP11")
cog.outl("")
cog.out(" using message_types = etl::type_list<")
for t in range(1, int(n)):
cog.out("T%s, " % t)
cog.outl("T%s>;" % int(n))
cog.outl("#endif")
cog.outl("")
cog.outl(" //********************************************")
cog.outl("#include \"private/diagnostic_uninitialized_push.h\"")
cog.outl(" message_packet()")
cog.outl(" ETL_CONSTEXPR message_packet() ETL_NOEXCEPT")
cog.outl(" : valid(false)")
cog.outl(" {")
cog.outl(" }")
@ -1058,6 +1205,62 @@ namespace etl
cog.outl("};")
]]]*/
/*[[[end]]]*/
//***************************************************************************
// Specialisation for 0 message types.
//***************************************************************************
template <>
class message_packet<void, void, void, void, void, void, void, void,
void, void, void, void, void, void, void, void>
{
public:
#if ETL_USING_CPP11
using message_types = etl::type_list<>;
#endif
ETL_CONSTEXPR message_packet() ETL_NOEXCEPT
: valid(false)
{
}
static ETL_CONSTEXPR bool accepts(etl::message_id_t)
{
return false;
}
static ETL_CONSTEXPR bool accepts(const etl::imessage&)
{
return false;
}
template <etl::message_id_t Id>
static ETL_CONSTEXPR bool accepts()
{
return false;
}
template <typename TMessage>
static ETL_CONSTEXPR typename etl::enable_if<etl::is_base_of<etl::imessage, TMessage>::value, bool>::type accepts()
{
return false;
}
bool is_valid() const
{
return valid;
}
enum
{
SIZE = 0U,
ALIGNMENT = 1U
};
private:
bool valid;
};
#endif
}

View File

@ -76,7 +76,7 @@ cog.outl("//********************************************************************
#include "placement_new.h"
#include "successor.h"
#include "type_traits.h"
#include "type_list.h"
#include <stdint.h>
namespace etl
@ -560,6 +560,114 @@ namespace etl
}
}
};
//***************************************************************************
// The definition for 0 message types.
//***************************************************************************
template <typename TDerived>
class message_router<TDerived> : public imessage_router
{
public:
using message_packet = etl::message_packet<>;
using message_types = etl::type_list<>;
//**********************************************
message_router()
: imessage_router(etl::imessage_router::MESSAGE_ROUTER)
{
}
//**********************************************
message_router(etl::imessage_router& successor_)
: imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_)
{
}
//**********************************************
message_router(etl::message_router_id_t id_)
: imessage_router(id_)
{
ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
}
//**********************************************
message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)
: imessage_router(id_, successor_)
{
ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
}
//**********************************************
using etl::imessage_router::receive;
void receive(const etl::imessage& msg) ETL_OVERRIDE
{
if (has_successor())
{
get_successor().receive(msg);
}
}
template <typename TMessage, typename etl::enable_if<etl::is_base_of<imessage, TMessage>::value, int>::type = 0>
void receive(const TMessage& msg)
{
#include "etl/private/diagnostic_array_bounds_push.h"
if (has_successor())
{
get_successor().receive(msg);
}
#include "etl/private/diagnostic_pop.h"
}
//**********************************************
using imessage_router::accepts;
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
if (has_successor())
{
return get_successor().accepts(id);
}
else
{
return false;
}
}
//********************************************
ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE
{
return false;
}
//********************************************
bool is_producer() const ETL_OVERRIDE
{
return true;
}
//********************************************
bool is_consumer() const ETL_OVERRIDE
{
return true;
}
};
//***************************************************************************
/// Helper to turn etl::type_list<TTypes...> into etl::message_router<TTypes...>
template <typename TDerived, typename TList>
struct message_router_from_type_list;
template <typename TDerived, typename... TMessageTypes>
struct message_router_from_type_list<TDerived, etl::type_list<TMessageTypes...>>
{
using type = etl::message_router<TDerived, TMessageTypes...>;
};
template <typename TDerived, typename TTypeList>
using message_router_from_type_list_t = typename message_router_from_type_list<TDerived, TTypeList>::type;
#else
//*************************************************************************************************
// For C++14 and below.
@ -574,8 +682,7 @@ namespace etl
cog.outl("//***************************************************************************")
cog.outl("template <typename TDerived,")
cog.out(" ")
cog.out("typename T1, ")
for n in range(2, int(Handlers)):
for n in range(1, int(Handlers)):
cog.out("typename T%s = void, " % n)
if n % 4 == 0:
cog.outl("")
@ -589,8 +696,17 @@ namespace etl
cog.out(" typedef etl::message_packet<")
for n in range(1, int(Handlers)):
cog.out("T%s, " % n)
cog.outl(" T%s> message_packet;" % int(Handlers))
cog.outl("T%s> message_packet;" % int(Handlers))
cog.outl("")
cog.outl("#if ETL_USING_CPP11")
cog.out(" using message_types = etl::type_list<")
for n in range(1, int(Handlers)):
cog.out("T%s, " % n)
cog.outl("T%s>;" % int(Handlers))
cog.outl("#endif")
cog.outl("")
cog.outl(" //**********************************************")
cog.outl(" message_router(etl::message_router_id_t id_)")
cog.outl(" : imessage_router(id_)")
@ -765,6 +881,15 @@ namespace etl
cog.out("T%s, " % t)
cog.outl(" T%s> message_packet;" % n)
cog.outl("")
cog.outl("#if ETL_USING_CPP11")
cog.out(" using message_types = etl::type_list<")
for t in range(1, n):
cog.out("T%s, " % t)
cog.outl("T%s>;" % n)
cog.outl("#endif")
cog.outl("")
cog.outl(" //**********************************************")
cog.outl(" message_router(etl::message_router_id_t id_)")
cog.outl(" : imessage_router(id_)")
@ -902,6 +1027,94 @@ namespace etl
cog.outl("};")
]]]*/
/*[[[end]]]*/
//***************************************************************************
// Specialisation for 0 message types.
//***************************************************************************
template <typename TDerived>
class message_router<TDerived, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void>
: public imessage_router
{
public:
typedef etl::message_packet<> message_packet;
#if ETL_USING_CPP11
using message_types = etl::type_list<>;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
: imessage_router(id_)
{
ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
}
//**********************************************
message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)
: imessage_router(id_, successor_)
{
ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
}
//**********************************************
message_router()
: imessage_router(etl::imessage_router::MESSAGE_ROUTER)
{
}
//**********************************************
message_router(etl::imessage_router& successor_)
: imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_)
{
}
//**********************************************
using etl::imessage_router::receive;
void receive(const etl::imessage& msg) ETL_OVERRIDE
{
#include "etl/private/diagnostic_array_bounds_push.h"
if (has_successor())
{
get_successor().receive(msg);
}
#include "etl/private/diagnostic_pop.h"
}
//**********************************************
using imessage_router::accepts;
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
if (has_successor())
{
return get_successor().accepts(id);
}
else
{
return false;
}
}
//********************************************
ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE
{
return false;
}
//********************************************
bool is_producer() const ETL_OVERRIDE
{
return true;
}
//********************************************
bool is_consumer() const ETL_OVERRIDE
{
return true;
}
};
#endif
}

View File

@ -59,6 +59,7 @@ SOFTWARE.
#include "largest.h"
#include "alignment.h"
#include "utility.h"
#include "type_list.h"
#include <stdint.h>
@ -75,19 +76,21 @@ namespace etl
private:
template <typename T>
static constexpr bool IsMessagePacket = etl::is_same_v< etl::remove_const_t<etl::remove_reference_t<T>>, etl::message_packet<TMessageTypes...>>;
static constexpr bool IsMessagePacket = etl::is_same_v<etl::remove_const_t<etl::remove_reference_t<T>>, etl::message_packet<TMessageTypes...>>;
template <typename T>
static constexpr bool IsInMessageList = etl::is_one_of_v<etl::remove_const_t<etl::remove_reference_t<T>>, TMessageTypes...>;
template <typename T>
static constexpr bool IsIMessage = etl::is_same_v<remove_const_t<etl::remove_reference_t<T>>, etl::imessage>;
static constexpr bool IsIMessage = etl::is_same_v<etl::remove_const_t<etl::remove_reference_t<T>>, etl::imessage>;
public:
using message_types = etl::type_list<TMessageTypes...>;
//********************************************
#include "private/diagnostic_uninitialized_push.h"
message_packet()
constexpr message_packet() noexcept
: valid(false)
{
}
@ -248,7 +251,7 @@ namespace etl
//**********************************************
template <typename TMessage>
static ETL_CONSTEXPR
typename etl::enable_if<etl::is_base_of<etl::imessage, TMessage>::value, bool>::type
typename etl::enable_if<etl::is_base_of<etl::imessage, TMessage>::value, bool>::type
accepts()
{
return accepts<TMessage::ID>();
@ -380,12 +383,138 @@ namespace etl
bool valid;
};
//***************************************************************************
// The definition for no message types.
//***************************************************************************
template <>
class message_packet<>
{
private:
template <typename T>
static constexpr bool IsMessagePacket = etl::is_same_v<etl::remove_const_t<etl::remove_reference_t<T>>, etl::message_packet<>>;
template <typename T>
static constexpr bool IsInMessageList = false;
template <typename T>
static constexpr bool IsIMessage = etl::is_same_v<etl::remove_const_t<etl::remove_reference_t<T>>, etl::imessage>;
public:
using message_types = etl::type_list<>;
//********************************************
#include "private/diagnostic_uninitialized_push.h"
constexpr message_packet() noexcept
{
}
#include "private/diagnostic_pop.h"
//**********************************************
message_packet(const message_packet& /*other*/)
{
}
#if ETL_USING_CPP11
//**********************************************
message_packet(message_packet&& /*other*/)
{
}
#endif
//**********************************************
void copy(const message_packet& /*other*/)
{
}
//**********************************************
void copy(message_packet&& /*other*/)
{
}
//**********************************************
#include "private/diagnostic_uninitialized_push.h"
message_packet& operator =(const message_packet& /*rhs*/)
{
return *this;
}
#include "private/diagnostic_pop.h"
//**********************************************
#include "private/diagnostic_uninitialized_push.h"
message_packet& operator =(message_packet&& /*rhs*/)
{
return *this;
}
#include "private/diagnostic_pop.h"
//********************************************
~message_packet()
{
}
//********************************************
bool is_valid() const
{
return false;
}
//**********************************************
static ETL_CONSTEXPR bool accepts(etl::message_id_t /*id*/)
{
return false;
}
//**********************************************
static ETL_CONSTEXPR bool accepts(const etl::imessage& /*msg*/)
{
return false;
}
//**********************************************
template <etl::message_id_t Id>
static ETL_CONSTEXPR bool accepts()
{
return false;
}
//**********************************************
template <typename TMessage>
static ETL_CONSTEXPR
typename etl::enable_if<etl::is_base_of<etl::imessage, TMessage>::value, bool>::type
accepts()
{
return false;
}
enum
{
SIZE = 0,
ALIGNMENT = 1
};
};
//***************************************************************************
/// Helper to turn etl::type_list<TTypes...> into etl::message_packet<TTypes...>
template <typename TList>
struct message_packet_from_type_list;
template <typename... TTypes>
struct message_packet_from_type_list<etl::type_list<TTypes...>>
{
using type = etl::message_packet<TTypes...>;
};
template <typename TTypeList>
using message_packet_from_type_list_t = typename message_packet_from_type_list<TTypeList>::type;
#else
//***************************************************************************
// The definition for all 16 message types.
//***************************************************************************
template <typename T1, typename T2 = void, typename T3 = void, typename T4 = void,
template <typename T1 = void, typename T2 = void, typename T3 = void, typename T4 = void,
typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void,
typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void,
typename T13 = void, typename T14 = void, typename T15 = void, typename T16 = void>
@ -393,9 +522,13 @@ namespace etl
{
public:
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>;
#endif
//********************************************
#include "private/diagnostic_uninitialized_push.h"
message_packet()
ETL_CONSTEXPR message_packet() ETL_NOEXCEPT
: valid(false)
{
}
@ -717,9 +850,13 @@ namespace etl
{
public:
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>;
#endif
//********************************************
#include "private/diagnostic_uninitialized_push.h"
message_packet()
ETL_CONSTEXPR message_packet() ETL_NOEXCEPT
: valid(false)
{
}
@ -1039,9 +1176,13 @@ namespace etl
{
public:
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>;
#endif
//********************************************
#include "private/diagnostic_uninitialized_push.h"
message_packet()
ETL_CONSTEXPR message_packet() ETL_NOEXCEPT
: valid(false)
{
}
@ -1358,9 +1499,13 @@ namespace etl
{
public:
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>;
#endif
//********************************************
#include "private/diagnostic_uninitialized_push.h"
message_packet()
ETL_CONSTEXPR message_packet() ETL_NOEXCEPT
: valid(false)
{
}
@ -1673,9 +1818,13 @@ namespace etl
{
public:
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>;
#endif
//********************************************
#include "private/diagnostic_uninitialized_push.h"
message_packet()
ETL_CONSTEXPR message_packet() ETL_NOEXCEPT
: valid(false)
{
}
@ -1982,9 +2131,13 @@ namespace etl
{
public:
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>;
#endif
//********************************************
#include "private/diagnostic_uninitialized_push.h"
message_packet()
ETL_CONSTEXPR message_packet() ETL_NOEXCEPT
: valid(false)
{
}
@ -2288,9 +2441,13 @@ namespace etl
{
public:
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>;
#endif
//********************************************
#include "private/diagnostic_uninitialized_push.h"
message_packet()
ETL_CONSTEXPR message_packet() ETL_NOEXCEPT
: valid(false)
{
}
@ -2591,9 +2748,13 @@ namespace etl
{
public:
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4, T5, T6, T7, T8, T9>;
#endif
//********************************************
#include "private/diagnostic_uninitialized_push.h"
message_packet()
ETL_CONSTEXPR message_packet() ETL_NOEXCEPT
: valid(false)
{
}
@ -2890,9 +3051,13 @@ namespace etl
{
public:
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4, T5, T6, T7, T8>;
#endif
//********************************************
#include "private/diagnostic_uninitialized_push.h"
message_packet()
ETL_CONSTEXPR message_packet() ETL_NOEXCEPT
: valid(false)
{
}
@ -3183,9 +3348,13 @@ namespace etl
{
public:
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4, T5, T6, T7>;
#endif
//********************************************
#include "private/diagnostic_uninitialized_push.h"
message_packet()
ETL_CONSTEXPR message_packet() ETL_NOEXCEPT
: valid(false)
{
}
@ -3473,9 +3642,13 @@ namespace etl
{
public:
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4, T5, T6>;
#endif
//********************************************
#include "private/diagnostic_uninitialized_push.h"
message_packet()
ETL_CONSTEXPR message_packet() ETL_NOEXCEPT
: valid(false)
{
}
@ -3760,9 +3933,13 @@ namespace etl
{
public:
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4, T5>;
#endif
//********************************************
#include "private/diagnostic_uninitialized_push.h"
message_packet()
ETL_CONSTEXPR message_packet() ETL_NOEXCEPT
: valid(false)
{
}
@ -4043,9 +4220,13 @@ namespace etl
{
public:
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4>;
#endif
//********************************************
#include "private/diagnostic_uninitialized_push.h"
message_packet()
ETL_CONSTEXPR message_packet() ETL_NOEXCEPT
: valid(false)
{
}
@ -4320,9 +4501,13 @@ namespace etl
{
public:
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3>;
#endif
//********************************************
#include "private/diagnostic_uninitialized_push.h"
message_packet()
ETL_CONSTEXPR message_packet() ETL_NOEXCEPT
: valid(false)
{
}
@ -4594,9 +4779,13 @@ namespace etl
{
public:
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2>;
#endif
//********************************************
#include "private/diagnostic_uninitialized_push.h"
message_packet()
ETL_CONSTEXPR message_packet() ETL_NOEXCEPT
: valid(false)
{
}
@ -4865,9 +5054,13 @@ namespace etl
{
public:
#if ETL_USING_CPP11
using message_types = etl::type_list<T1>;
#endif
//********************************************
#include "private/diagnostic_uninitialized_push.h"
message_packet()
ETL_CONSTEXPR message_packet() ETL_NOEXCEPT
: valid(false)
{
}
@ -5124,6 +5317,62 @@ namespace etl
typename etl::aligned_storage<SIZE, ALIGNMENT>::type data;
bool valid;
};
//***************************************************************************
// Specialisation for 0 message types.
//***************************************************************************
template <>
class message_packet<void, void, void, void, void, void, void, void,
void, void, void, void, void, void, void, void>
{
public:
#if ETL_USING_CPP11
using message_types = etl::type_list<>;
#endif
ETL_CONSTEXPR message_packet() ETL_NOEXCEPT
: valid(false)
{
}
static ETL_CONSTEXPR bool accepts(etl::message_id_t)
{
return false;
}
static ETL_CONSTEXPR bool accepts(const etl::imessage&)
{
return false;
}
template <etl::message_id_t Id>
static ETL_CONSTEXPR bool accepts()
{
return false;
}
template <typename TMessage>
static ETL_CONSTEXPR typename etl::enable_if<etl::is_base_of<etl::imessage, TMessage>::value, bool>::type accepts()
{
return false;
}
bool is_valid() const
{
return valid;
}
enum
{
SIZE = 0U,
ALIGNMENT = 1U
};
private:
bool valid;
};
#endif
}

View File

@ -64,7 +64,7 @@ SOFTWARE.
#include "placement_new.h"
#include "successor.h"
#include "type_traits.h"
#include "type_list.h"
#include <stdint.h>
namespace etl
@ -548,6 +548,114 @@ namespace etl
}
}
};
//***************************************************************************
// The definition for 0 message types.
//***************************************************************************
template <typename TDerived>
class message_router<TDerived> : public imessage_router
{
public:
using message_packet = etl::message_packet<>;
using message_types = etl::type_list<>;
//**********************************************
message_router()
: imessage_router(etl::imessage_router::MESSAGE_ROUTER)
{
}
//**********************************************
message_router(etl::imessage_router& successor_)
: imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_)
{
}
//**********************************************
message_router(etl::message_router_id_t id_)
: imessage_router(id_)
{
ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
}
//**********************************************
message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)
: imessage_router(id_, successor_)
{
ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
}
//**********************************************
using etl::imessage_router::receive;
void receive(const etl::imessage& msg) ETL_OVERRIDE
{
if (has_successor())
{
get_successor().receive(msg);
}
}
template <typename TMessage, typename etl::enable_if<etl::is_base_of<imessage, TMessage>::value, int>::type = 0>
void receive(const TMessage& msg)
{
#include "etl/private/diagnostic_array_bounds_push.h"
if (has_successor())
{
get_successor().receive(msg);
}
#include "etl/private/diagnostic_pop.h"
}
//**********************************************
using imessage_router::accepts;
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
if (has_successor())
{
return get_successor().accepts(id);
}
else
{
return false;
}
}
//********************************************
ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE
{
return false;
}
//********************************************
bool is_producer() const ETL_OVERRIDE
{
return true;
}
//********************************************
bool is_consumer() const ETL_OVERRIDE
{
return true;
}
};
//***************************************************************************
/// Helper to turn etl::type_list<TTypes...> into etl::message_router<TTypes...>
template <typename TDerived, typename TList>
struct message_router_from_type_list;
template <typename TDerived, typename... TMessageTypes>
struct message_router_from_type_list<TDerived, etl::type_list<TMessageTypes...>>
{
using type = etl::message_router<TDerived, TMessageTypes...>;
};
template <typename TDerived, typename TTypeList>
using message_router_from_type_list_t = typename message_router_from_type_list<TDerived, TTypeList>::type;
#else
//*************************************************************************************************
// For C++14 and below.
@ -556,7 +664,7 @@ namespace etl
// The definition for all 16 message types.
//***************************************************************************
template <typename TDerived,
typename T1, typename T2 = void, typename T3 = void, typename T4 = void,
typename T1 = void, typename T2 = void, typename T3 = void, typename T4 = void,
typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void,
typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void,
typename T13 = void, typename T14 = void, typename T15 = void, typename T16 = void>
@ -564,7 +672,11 @@ namespace etl
{
public:
typedef etl::message_packet<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16> message_packet;
typedef etl::message_packet<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16> message_packet;
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
@ -717,6 +829,10 @@ namespace etl
typedef etl::message_packet<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> message_packet;
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
: imessage_router(id_)
@ -868,6 +984,10 @@ namespace etl
typedef etl::message_packet<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14> message_packet;
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
: imessage_router(id_)
@ -1018,6 +1138,10 @@ namespace etl
typedef etl::message_packet<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> message_packet;
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
: imessage_router(id_)
@ -1166,6 +1290,10 @@ namespace etl
typedef etl::message_packet<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> message_packet;
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
: imessage_router(id_)
@ -1313,6 +1441,10 @@ namespace etl
typedef etl::message_packet<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> message_packet;
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
: imessage_router(id_)
@ -1459,6 +1591,10 @@ namespace etl
typedef etl::message_packet<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> message_packet;
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
: imessage_router(id_)
@ -1604,6 +1740,10 @@ namespace etl
typedef etl::message_packet<T1, T2, T3, T4, T5, T6, T7, T8, T9> message_packet;
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4, T5, T6, T7, T8, T9>;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
: imessage_router(id_)
@ -1747,6 +1887,10 @@ namespace etl
typedef etl::message_packet<T1, T2, T3, T4, T5, T6, T7, T8> message_packet;
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4, T5, T6, T7, T8>;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
: imessage_router(id_)
@ -1889,6 +2033,10 @@ namespace etl
typedef etl::message_packet<T1, T2, T3, T4, T5, T6, T7> message_packet;
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4, T5, T6, T7>;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
: imessage_router(id_)
@ -2029,6 +2177,10 @@ namespace etl
typedef etl::message_packet<T1, T2, T3, T4, T5, T6> message_packet;
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4, T5, T6>;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
: imessage_router(id_)
@ -2168,6 +2320,10 @@ namespace etl
typedef etl::message_packet<T1, T2, T3, T4, T5> message_packet;
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4, T5>;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
: imessage_router(id_)
@ -2305,6 +2461,10 @@ namespace etl
typedef etl::message_packet<T1, T2, T3, T4> message_packet;
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3, T4>;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
: imessage_router(id_)
@ -2441,6 +2601,10 @@ namespace etl
typedef etl::message_packet<T1, T2, T3> message_packet;
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2, T3>;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
: imessage_router(id_)
@ -2576,6 +2740,10 @@ namespace etl
typedef etl::message_packet<T1, T2> message_packet;
#if ETL_USING_CPP11
using message_types = etl::type_list<T1, T2>;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
: imessage_router(id_)
@ -2710,6 +2878,10 @@ namespace etl
typedef etl::message_packet< T1> message_packet;
#if ETL_USING_CPP11
using message_types = etl::type_list<T1>;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
: imessage_router(id_)
@ -2830,6 +3002,94 @@ namespace etl
return true;
}
};
//***************************************************************************
// Specialisation for 0 message types.
//***************************************************************************
template <typename TDerived>
class message_router<TDerived, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void>
: public imessage_router
{
public:
typedef etl::message_packet<> message_packet;
#if ETL_USING_CPP11
using message_types = etl::type_list<>;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
: imessage_router(id_)
{
ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
}
//**********************************************
message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)
: imessage_router(id_, successor_)
{
ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
}
//**********************************************
message_router()
: imessage_router(etl::imessage_router::MESSAGE_ROUTER)
{
}
//**********************************************
message_router(etl::imessage_router& successor_)
: imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_)
{
}
//**********************************************
using etl::imessage_router::receive;
void receive(const etl::imessage& msg) ETL_OVERRIDE
{
#include "etl/private/diagnostic_array_bounds_push.h"
if (has_successor())
{
get_successor().receive(msg);
}
#include "etl/private/diagnostic_pop.h"
}
//**********************************************
using imessage_router::accepts;
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
if (has_successor())
{
return get_successor().accepts(id);
}
else
{
return false;
}
}
//********************************************
ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE
{
return false;
}
//********************************************
bool is_producer() const ETL_OVERRIDE
{
return true;
}
//********************************************
bool is_consumer() const ETL_OVERRIDE
{
return true;
}
};
#endif
}

View File

@ -31,6 +31,7 @@ SOFTWARE.
#include "platform.h"
#include "static_assert.h"
#include "type_list.h"
#if ETL_USING_CPP11
namespace etl
@ -57,7 +58,16 @@ namespace etl
{
ETL_STATIC_ASSERT(Index < sizeof...(TTypes), "etl::nth_type index 'Index' out of bounds");
using type = typename private_nth_type::nth_type_helper<Index, TTypes...>::type;
using type = typename private_nth_type::nth_type_helper<Index, TTypes...>::type;
using type_list = etl::type_list<TTypes...>;
};
//***********************************
template <size_t Index, typename... TTypes>
struct nth_type<Index, etl::type_list<TTypes...>>
{
using type = typename nth_type<Index, TTypes...>::type;
using type_list = typename nth_type<Index, TTypes...>::type_list;
};
//***********************************

View File

@ -57,6 +57,7 @@ SOFTWARE.
#include "exception.h"
#include "error_handler.h"
#include "utility.h"
#include "type_list.h"
namespace etl
{
@ -308,6 +309,7 @@ namespace etl
using observer<T1>::notification;
using observer<TRest...>::notification;
using type_list = etl::type_list<T1, TRest...>;
};
//*****************************************************************
@ -319,6 +321,8 @@ namespace etl
{
public:
using type_list = etl::type_list<T1>;
virtual ~observer() = default;
virtual void notification(T1) = 0;
@ -333,11 +337,27 @@ namespace etl
{
public:
using type_list = etl::type_list<>;
virtual ~observer() = default;
virtual void notification() = 0;
};
//***************************************************************************
/// Helper to turn etl::type_list<TTypes...> into etl::observer<TTypes...>
template <typename TList>
struct observer_from_type_list;
template <typename... TTypes>
struct observer_from_type_list<etl::type_list<TTypes...>>
{
using type = etl::observer<TTypes...>;
};
template <typename TTypeList>
using observer_from_type_list_t = typename observer_from_type_list<TTypeList>::type;
#else
//*********************************************************************

View File

@ -370,7 +370,6 @@ namespace etl
//***************************************************************************
/// A template class that can store any of the types defined in the template parameter list.
/// Supports up to 8 types.
///\ingroup variant
//***************************************************************************
template <typename... TTypes>
@ -378,6 +377,8 @@ namespace etl
{
public:
using type_list = etl::type_list<TTypes...>;
//***************************************************************************
/// get() is a friend function.
//***************************************************************************
@ -1222,7 +1223,7 @@ namespace etl
//***************************************************************************
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<etl::type_list<TTypes...>, T>::value;
return (Index == variant_npos) ? false : (v.index() == Index);
@ -1853,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

@ -45,6 +45,7 @@ SOFTWARE.
#include "type_traits.h"
#include "utility.h"
#include "functional.h"
#include "type_list.h"
#include "private/tuple_element.h"
#include "private/tuple_size.h"
@ -131,6 +132,7 @@ namespace etl
using value_type = void; ///< The type contained by this tuple.
using this_type = tuple<>; ///< The type of this tuple.
using base_type = void; ///< The type of the base tuple.
using type_list = etl::type_list<>; ///< The type list for this tuple.
using index_sequence_type = etl::make_index_sequence<0>; ///< The index_sequence type for this tuple.
//*********************************
@ -233,6 +235,7 @@ namespace etl
using value_type = THead; ///< The type contained by this tuple.
using this_type = tuple<THead, TTail...>; ///< The type of this tuple.
using base_type = tuple<TTail...>; ///< The type of the base tuple.
using type_list = etl::type_list<THead, TTail...>; ///< The type list for this tuple.
using index_sequence_type = etl::make_index_sequence<number_of_types<THead, TTail...>()>; ///< The index_sequence type for this tuple.
//*********************************
@ -1273,6 +1276,20 @@ namespace etl
{
lhs.swap(rhs);
}
//***************************************************************************
/// Helper to turn etl::type_list<TTypes...> into etl::tuple<TTypes...>
template <typename TList>
struct tuple_from_type_list;
template <typename... TTypes>
struct tuple_from_type_list<etl::type_list<TTypes...>>
{
using type = etl::tuple<TTypes...>;
};
template <typename TTypeList>
using tuple_from_type_list_t = typename tuple_from_type_list<TTypeList>::type;
}
namespace std

View File

@ -53,6 +53,17 @@ namespace etl
template <typename... TTypes>
struct type_list;
template <typename T>
struct is_type_list : etl::false_type {};
template <typename... TTypes>
struct is_type_list<etl::type_list<TTypes...>> : etl::true_type {};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_type_list_v = is_type_list<T>::value;
#endif
//***************************************************************************
/// The empty type list.
//***************************************************************************

View File

@ -565,8 +565,31 @@ namespace etl
template <size_t Count>
using make_index_sequence = typename private_integer_sequence::make_index_sequence<Count, etl::integer_sequence<size_t>>::type;
//***********************************
// Helper to support both parameter packs and etl::type_list<T...>
// Forward declare etl::type_list to allow use without including type_list.h
template <typename... TTypes>
using make_index_sequence_for = typename private_integer_sequence::make_index_sequence<sizeof...(TTypes), etl::integer_sequence<size_t>>::type;
struct type_list;
namespace private_make_index_sequence_for
{
// Generic pack form
template <typename... TTypes>
struct impl
{
using type = typename private_integer_sequence::make_index_sequence<sizeof...(TTypes), etl::integer_sequence<size_t>>::type;
};
// etl::type_list form
template <typename... TTypes>
struct impl<etl::type_list<TTypes...>> : impl<TTypes...>
{
};
}
// Accepts either a parameter pack of types or a single etl::type_list<T...>
template <typename... TTypes>
using make_index_sequence_for = typename private_make_index_sequence_for::impl<TTypes...>::type;
//***********************************
template <size_t... Indices>

View File

@ -33,6 +33,7 @@ SOFTWARE.
#include "platform.h"
#include "type_traits.h"
#include "type_list.h"
//*****************************************************************************
///\defgroup visitor visitor
@ -64,6 +65,7 @@ namespace etl
using visitable<T1>::accept;
using visitable<Types...>::accept;
using type_list = etl::type_list<T1, Types...>;
};
//*****************************************************************
@ -75,11 +77,27 @@ namespace etl
{
public:
using type_list = etl::type_list<T1>;
virtual ~visitable() = default;
virtual void accept(T1&) = 0;
};
//***************************************************************************
/// Helper to turn etl::type_list<TTypes...> into etl::visitable<TTypes...>
template <typename TList>
struct visitable_from_type_list;
template <typename... TTypes>
struct visitable_from_type_list<etl::type_list<TTypes...>>
{
using type = etl::visitable<TTypes...>;
};
template <typename TTypeList>
using visitable_from_type_list_t = typename visitable_from_type_list<TTypeList>::type;
#else
//*****************************************************************
@ -187,6 +205,20 @@ namespace etl
virtual void visit(T1) = 0;
};
//***************************************************************************
/// Helper to turn etl::type_list<TTypes...> into etl::visitor<TTypes...>
template <typename TList>
struct visitor_from_type_list;
template <typename... TTypes>
struct visitor_from_type_list<etl::type_list<TTypes...>>
{
using type = etl::visitor<TTypes...>;
};
template <typename TTypeList>
using visitor_from_type_list_t = typename visitor_from_type_list<TTypeList>::type;
#else
//*****************************************************************

View File

@ -86,7 +86,6 @@ add_executable(etl_tests
test_closure.cpp
test_closure_constexpr.cpp
test_compare.cpp
test_concepts.cpp
test_constant.cpp
test_const_map.cpp
test_const_map_constexpr.cpp
@ -184,7 +183,6 @@ add_executable(etl_tests
test_flat_multiset.cpp
test_flat_set.cpp
test_fnv_1.cpp
test_format.cpp
test_format_spec.cpp
test_forward_list.cpp
test_forward_list_shared_pool.cpp
@ -196,12 +194,10 @@ add_executable(etl_tests
test_hash.cpp
test_hfsm.cpp
test_hfsm_recurse_to_inner_state_on_start.cpp
test_hfsm_transition_on_enter.cpp
test_histogram.cpp
test_index_of_type.cpp
test_indirect_vector.cpp
test_indirect_vector_external_buffer.cpp
test_inplace_function.cpp
test_instance_count.cpp
test_integral_limits.cpp
test_intrusive_forward_list.cpp
@ -210,9 +206,7 @@ add_executable(etl_tests
test_intrusive_queue.cpp
test_intrusive_stack.cpp
test_invert.cpp
test_invoke.cpp
test_io_port.cpp
test_is_invocable.cpp
test_iterator.cpp
test_jenkins.cpp
test_largest.cpp
@ -263,7 +257,6 @@ add_executable(etl_tests
test_poly_span_fixed_extent.cpp
test_pool.cpp
test_pool_external_buffer.cpp
test_print.cpp
test_priority_queue.cpp
test_pseudo_moving_average.cpp
test_quantize.cpp
@ -292,7 +285,6 @@ add_executable(etl_tests
test_scaled_rounding.cpp
test_set.cpp
test_shared_message.cpp
test_signal.cpp
test_singleton.cpp
test_singleton_base.cpp
test_smallest.cpp

View File

@ -110,6 +110,7 @@ SOFTWARE.
#define ETL_FLAT_SET_FORCE_CPP03_IMPLEMENTATION
#define ETL_FLAT_MULTISET_FORCE_CPP03_IMPLEMENTATION
#define ETL_VARIANT_POOL_FORCE_CPP03_IMPLEMENTATION
#define ETL_VISITOR_FORCE_CPP03_IMPLEMENTATION
#endif
#if defined(ETL_FORCE_TEST_CPP11)

View File

@ -29,7 +29,6 @@ SOFTWARE.
#include "unit_test_framework.h"
#include "etl/platform.h"
#include "etl/message_packet.h"
#include <string>
@ -200,8 +199,15 @@ namespace
{
};
using NullPacket = etl::message_packet<>;
using Packet = etl::message_packet<Message1, Message2, Message3>;
#if ETL_USING_CPP17 && !defined(ETL_MESSAGE_PACKET_FORCE_CPP03_IMPLEMENTATION)
using MessageTypes = etl::type_list<Message1, Message2, Message3>;
using PacketFromMessageTypes = etl::message_packet_from_type_list_t<MessageTypes>;
#endif
struct Object
{
void Push(const etl::message_packet<Message1, Message2>& p)
@ -224,12 +230,22 @@ namespace
Packet packet1(message1);
Packet packet2(message2);
#if ETL_USING_CPP17 && !defined(ETL_MESSAGE_PACKET_FORCE_CPP03_IMPLEMENTATION)
PacketFromMessageTypes packet3(message3);
#else
Packet packet3(message3);
#endif
// Should cause a static assert.
//Packet packet4(message4);
//Packet packet4((Message4()));
CHECK_TRUE((std::is_same<etl::type_list<Message1, Message2, Message3>, typename Packet::message_types>::value));
#if ETL_USING_CPP17 && !defined(ETL_MESSAGE_PACKET_FORCE_CPP03_IMPLEMENTATION)
CHECK_TRUE((std::is_same<etl::type_list<Message1, Message2, Message3>, typename PacketFromMessageTypes::message_types>::value));
#endif
CHECK_TRUE((std::is_same<etl::type_list<>, typename NullPacket::message_types>::value));
CHECK_EQUAL(MESSAGE1, packet1.get().get_message_id());
CHECK_EQUAL(MESSAGE2, packet2.get().get_message_id());
CHECK_EQUAL(MESSAGE3, packet3.get().get_message_id());

View File

@ -49,6 +49,7 @@ namespace
enum
{
ROUTER0,
ROUTER1,
ROUTER2,
ROUTER3
@ -120,9 +121,28 @@ namespace
Message5 message5;
//***************************************************************************
// Router that handles messages 1, 2, 3, 4 and 5 and returns nothing.
// Router that handles no messages.
//***************************************************************************
class Router0 : public etl::message_router<Router0>
{
public:
Router0()
: message_router(ROUTER0)
{
}
};
//***************************************************************************
// Router that handles messages 1, 2, 3, 4 and 5 and returns nothing.
// Created from a type list.
//***************************************************************************
#if ETL_USING_CPP17 && !defined(ETL_MESSAGE_ROUTER_FORCE_CPP03_IMPLEMENTATION)
using Router1Messages = etl::type_list<Message1, Message2, Message3, Message4, Message5>;
class Router1 : public etl::message_router_from_type_list_t<Router1, Router1Messages>
#else
class Router1 : public etl::message_router<Router1, Message1, Message2, Message3, Message4, Message5>
#endif
{
public:
@ -135,7 +155,6 @@ namespace
message_unknown_count(0),
callback_count(0)
{
}
void on_receive(const Message1& msg)
@ -334,14 +353,14 @@ namespace
Router1 r1;
Router2 r2;
p_router = &r1;
Message1 message1(r2);
Message2 message2(r2);
Message3 message3(r2);
Message4 message4(r2);
// CHECK(!r1.is_null_router());
p_router = &r1;
CHECK(!r1.is_null_router());
CHECK(r1.is_producer());
CHECK(r1.is_consumer());
@ -378,6 +397,59 @@ namespace
CHECK_EQUAL(4, r2.callback_count);
}
//*************************************************************************
TEST(message_router_with_no_message_types)
{
Router0 r0;
Router1 r1;
Router2 r2;
Message1 message1(r2);
Message2 message2(r2);
Message3 message3(r2);
Message4 message4(r2);
r0.append_successor(r1); // All messages are passed to r1.
CHECK_TRUE((etl::is_same<Router0::message_types, etl::type_list<>>::value));
CHECK(!r0.is_null_router());
CHECK(r0.is_producer());
CHECK(r0.is_consumer());
r1.receive(message1);
CHECK_EQUAL(1, r1.message1_count);
CHECK_EQUAL(0, r1.message2_count);
CHECK_EQUAL(0, r1.message3_count);
CHECK_EQUAL(0, r1.message4_count);
CHECK_EQUAL(0, r1.message_unknown_count);
CHECK_EQUAL(1, r2.callback_count);
r1.receive(message2);
CHECK_EQUAL(1, r1.message1_count);
CHECK_EQUAL(1, r1.message2_count);
CHECK_EQUAL(0, r1.message3_count);
CHECK_EQUAL(0, r1.message4_count);
CHECK_EQUAL(0, r1.message_unknown_count);
CHECK_EQUAL(2, r2.callback_count);
r1.receive(message3);
CHECK_EQUAL(1, r1.message1_count);
CHECK_EQUAL(1, r1.message2_count);
CHECK_EQUAL(1, r1.message3_count);
CHECK_EQUAL(0, r1.message4_count);
CHECK_EQUAL(0, r1.message_unknown_count);
CHECK_EQUAL(3, r2.callback_count);
r1.receive(message4);
CHECK_EQUAL(1, r1.message1_count);
CHECK_EQUAL(1, r1.message2_count);
CHECK_EQUAL(1, r1.message3_count);
CHECK_EQUAL(1, r1.message4_count);
CHECK_EQUAL(0, r1.message_unknown_count);
CHECK_EQUAL(4, r2.callback_count);
}
//*************************************************************************
TEST(message_null_router)
{
@ -389,7 +461,7 @@ namespace
Message3 message3(null_router);
Message4 message4(null_router);
// CHECK(null_router.is_null_router());
CHECK(null_router.is_null_router());
CHECK(!null_router.is_producer());
CHECK(!null_router.is_consumer());

View File

@ -29,6 +29,7 @@ SOFTWARE.
#include "unit_test_framework.h"
#include "etl/nth_type.h"
#include "etl/type_list.h"
#include <type_traits>
namespace
@ -42,5 +43,15 @@ namespace
CHECK((std::is_same<etl::nth_type_t<1, int, long, double>, long>::value));
CHECK((std::is_same<etl::nth_type_t<2, int, long, double>, double>::value));
}
//*************************************************************************
TEST(test_nth_type_from_type_list)
{
using types = etl::type_list<int, long, double>;
CHECK((std::is_same<etl::nth_type_t<0, types>, int>::value));
CHECK((std::is_same<etl::nth_type_t<1, types>, long>::value));
CHECK((std::is_same<etl::nth_type_t<2, types>, double>::value));
}
}
}

View File

@ -68,12 +68,24 @@ namespace
// The Notification2 is passed by reference.
// The Notification3 is passed by const reference.
//*****************************************************************************
typedef etl::observer<Notification1, Notification2&, const Notification3&> ObserverType;
using ObserverType = etl::observer<Notification1, Notification2&, const Notification3&>;
#if !defined(ETL_OBSERVER_FORCE_CPP03_IMPLEMENTATION)
//*****************************************************************************
// The observer base type.
// Declare what notifications you want to observe and how they are passed to 'notification'.
// The Notification1 is passed by value.
// The Notification2 is passed by reference.
// The Notification3 is passed by const reference.
//*****************************************************************************
using NotificationList = etl::type_list<Notification1, Notification2&, const Notification3&>;
using ObserverFromTypeList = etl::observer_from_type_list_t<NotificationList>;
#endif
//*****************************************************************************
// The observer base type that does not take a notification type.
//*****************************************************************************
typedef etl::observer<void, int> ObserverVoidIntType;
using ObserverVoidIntType = etl::observer<void, int>;
}
//*****************************************************************************
@ -115,6 +127,29 @@ public:
}
};
#if !defined(ETL_OBSERVER_FORCE_CPP03_IMPLEMENTATION)
//*****************************************************************************
// The concrete observable 3 class.
//*****************************************************************************
class Observable3 : public etl::observable<ObserverFromTypeList, 2>
{
public:
Notification1 data1;
Notification2 data2;
Notification1& data3 = data1;
//*********************************
// Notify all of the observers.
//*********************************
void send_notifications()
{
notify_observers(data3);
notify_observers(data2);
}
};
#endif
//*****************************************************************************
// The concrete observable 3 class.
//*****************************************************************************
@ -229,6 +264,53 @@ public:
int data3_count;
};
#if !defined(ETL_OBSERVER_FORCE_CPP03_IMPLEMENTATION)
//*****************************************************************************
// The third observer type.
// If any one of the overloads is missing or a parameter declaration is incorrect
// then the class will be 'abstract' and will not compile.
//*****************************************************************************
class Observer3 : public ObserverFromTypeList
{
public:
Observer3()
: data1_count(0)
, data2_count(0)
, data3_count(0)
{
}
//*******************************************
// Notification1 is passed by value.
//*******************************************
void notification(Notification1 /*data1*/)
{
++data1_count;
}
//*******************************************
// Notification2 is passed by reference.
//*******************************************
void notification(Notification2& /*data2*/)
{
++data2_count;
}
//*******************************************
// Notification3 is passed by const reference.
//*******************************************
void notification(const Notification3& /*data3*/)
{
++data3_count;
}
int data1_count;
int data2_count;
int data3_count;
};
#endif
//*****************************************************************************
// The third observer type.
// If any one of the overloads is missing or a parameter declaration is incorrect
@ -399,6 +481,27 @@ namespace
CHECK_EQUAL(3, observer2.data1_count);
}
#if !defined(ETL_OBSERVER_FORCE_CPP03_IMPLEMENTATION)
//*************************************************************************
TEST(test_observer_created_from_a_type_list)
{
// The observable objects.
Observable3 observable3;
// The observer objects.
Observer3 observer3;
observable3.add_observer(observer3);
// Send the notifications.
observable3.send_notifications(); // Updates data1 & data2.
CHECK_EQUAL(1, observer3.data1_count);
CHECK_EQUAL(1, observer3.data2_count);
CHECK_EQUAL(0, observer3.data3_count);
}
#endif
//*************************************************************************
TEST(test_8_notifications)
{

View File

@ -31,6 +31,7 @@ SOFTWARE.
#include "data.h"
#include "etl/tuple.h"
#include "etl/type_list.h"
#include <string>
#include <array>
@ -103,6 +104,26 @@ namespace
CHECK_TRUE((std::is_same<Data, etl::tuple_element_t<3, Tuple>>::value));
}
//*************************************************************************
TEST(test_tuple_from_type_list)
{
using TypeList = etl::type_list<int, double, int, Data>;
using TupleFromTypeList = etl::tuple_from_type_list_t<TypeList>;
using Tuple = etl::tuple<int, double, int, Data>;
CHECK_TRUE((std::is_same<Tuple, TupleFromTypeList>::value));
CHECK_TRUE((std::is_same<TypeList, TupleFromTypeList::type_list>::value));
}
//*************************************************************************
TEST(test_tuple_type_list)
{
using Tuple = etl::tuple<int, double, int, Data>;
using TupleTypes = etl::type_list<int, double, int, Data>;
CHECK_TRUE((std::is_same<TupleTypes, Tuple::type_list>::value));
}
//*************************************************************************
TEST(test_default_constructor)
{

View File

@ -37,6 +37,24 @@ namespace
#if ETL_USING_CPP11
SUITE(test_type_list)
{
//*************************************************************************
TEST(test_is_type_list)
{
using t0 = etl::type_list<>;
using t1 = etl::type_list<char, int, uint32_t>;
using t2 = int;
CHECK_TRUE((etl::is_type_list<t0>::value));
CHECK_TRUE((etl::is_type_list<t1>::value));
CHECK_FALSE((etl::is_type_list<t2>::value));
#if ETL_USING_CPP17
CHECK_TRUE((etl::is_type_list_v<t0>));
CHECK_TRUE((etl::is_type_list_v<t1>));
CHECK_FALSE((etl::is_type_list_v<t2>));
#endif
}
//*************************************************************************
TEST(test_type_list_select)
{

View File

@ -863,5 +863,39 @@ namespace
CHECK_TRUE(E::B == (etl::nontype_t<E, E::B>::value));
}
#endif
//*********************************
TEST(test_make_index_sequence_for_pack_matches_expected)
{
struct T1 {};
struct T2 {};
struct T3 {};
using seq12 = etl::make_index_sequence_for<T1, T2>;
using seq123 = etl::make_index_sequence_for<T1, T2, T3>;
using expect12 = etl::index_sequence<0U, 1U>;
using expect123 = etl::index_sequence<0U, 1U, 2U>;
CHECK_TRUE((std::is_same<seq12, expect12>::value));
CHECK_TRUE((std::is_same<seq123, expect123>::value));
}
//*********************************
TEST(test_make_index_sequence_for_type_list_matches_expected)
{
struct T1 {};
struct T2 {};
struct T3 {};
using list12 = etl::type_list<T1, T2>;
using list123 = etl::type_list<T1, T2, T3>;
using seq12 = etl::make_index_sequence_for<list12>;
using seq123 = etl::make_index_sequence_for<list123>;
using expect12 = etl::index_sequence<0U, 1U>;
using expect123 = etl::index_sequence<0U, 1U, 2U>;
CHECK_TRUE((std::is_same<seq12, expect12>::value));
CHECK_TRUE((std::is_same<seq123, expect123>::value));
}
}
}

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)
{
@ -462,6 +504,8 @@ namespace
test_variant_t variant_etl;
CHECK_TRUE((std::is_same<test_variant_t::type_list, etl::type_list<DefaultConstructible, int, std::string>>::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));

View File

@ -746,6 +746,32 @@ namespace
CHECK_FALSE(etl::is_visitor<NotVisitor>::value);
#endif
}
#if !defined(ETL_VISITOR_FORCE_CPP03_IMPLEMENTATION)
//*************************************************************************
TEST(test_visitor_from_type_list)
{
using Visitor1 = etl::visitor<Square&, Circle&, const Triangle&>;
using TypeList = etl::type_list<Square&, Circle&, const Triangle&>;
using Visitor2 = etl::visitor_from_type_list_t<TypeList>;
CHECK_TRUE((std::is_same<Visitor1, Visitor2>::value));
}
#endif
#if !defined(ETL_VISITOR_FORCE_CPP03_IMPLEMENTATION)
//*************************************************************************
TEST(test_visitable_from_type_list)
{
using Visitable1 = etl::visitable<DrawVisitorType, LogVisitorType>;
using TypeList = etl::type_list<DrawVisitorType, LogVisitorType>;
using Visitable2 = etl::visitable_from_type_list_t<TypeList>;
CHECK_TRUE((std::is_same<Visitable1, Visitable2>::value));
}
#endif
}
}