Work in progress

This commit is contained in:
John Wellbelove 2025-12-24 20:20:13 +00:00
parent 92e33bb974
commit 8320b35d47
3 changed files with 164 additions and 2 deletions

View File

@ -550,9 +550,158 @@ namespace etl
}
}
};
#elif ETL_USING_CPP14 && !defined(ETL_MESSAGE_ROUTER_FORCE_CPP03_IMPLEMENTATION)
//*************************************************************************************************
// Unified C++11/14 variadic implementation (no fold expressions).
//*************************************************************************************************
template <typename TDerived, typename... TMessageTypes>
class message_router : public imessage_router
{
public:
typedef etl::message_packet<TMessageTypes...> message_packet;
#if ETL_USING_CPP11
using type_list = etl::type_list<TMessageTypes...>;
#endif
// Constructors (inherit public base ones)
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;
// Route by runtime message_id with pack expansion via initializer list.
void receive(const etl::imessage& msg) ETL_OVERRIDE
{
const etl::message_id_t id = msg.get_message_id();
bool handled = false;
#include "etl/private/diagnostic_array_bounds_push.h"
// Expand across TMessageTypes... and attempt cast/dispatch on matching IDs.
int dummy[] = {0, (handled = handled || try_receive_one<TMessageTypes>(id, msg), 0)...};
(void)dummy;
#include "etl/private/diagnostic_pop.h"
if (!handled)
{
if (has_successor())
{
get_successor().receive(msg);
}
else
{
static_cast<TDerived*>(this)->on_receive_unknown(msg);
}
}
}
// Overload for concrete message types; forwards to on_receive or successor.
template <typename TMessage>
typename etl::enable_if<etl::is_base_of<imessage, TMessage>::value, void>::type
receive(const TMessage& msg)
{
#include "etl/private/diagnostic_array_bounds_push.h"
if (is_in_message_set<TMessage>())
{
static_cast<TDerived*>(this)->on_receive(msg);
}
else
{
if (has_successor())
{
get_successor().receive(msg);
}
else
{
static_cast<TDerived*>(this)->on_receive_unknown(msg);
}
}
#include "etl/private/diagnostic_pop.h"
}
using imessage_router::accepts;
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
bool accepted = false;
int dummy[] = {0, (accepted = accepted || accepts_one<TMessageTypes>(id), 0)...};
(void)dummy;
if (!accepted)
{
if (has_successor())
{
return get_successor().accepts(id);
}
}
return accepted;
}
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; }
private:
// Helper: is T in the message set?
template <typename T>
static ETL_CONSTEXPR bool is_in_message_set()
{
return etl::is_one_of<T, TMessageTypes...>::value;
}
// Try to handle one type by ID match and cast.
template <typename TMessage>
bool try_receive_one(etl::message_id_t id, const etl::imessage& msg)
{
if (TMessage::ID == id)
{
static_cast<TDerived*>(this)->on_receive(static_cast<const TMessage&>(msg));
return true;
}
return false;
}
// Accepts one type by ID
template <typename TMessage>
bool accepts_one(etl::message_id_t id) const
{
return TMessage::ID == id;
}
};
// Convenience bridge: allow message_router<TDerived, etl::type_list<Ts...>>
template <typename TDerived, typename... TMessageTypes>
class message_router<TDerived, etl::type_list<TMessageTypes...>>
: public message_router<TDerived, TMessageTypes...>
{
public:
typedef message_router<TDerived, TMessageTypes...> base_type;
#if ETL_USING_CPP11
using type_list = etl::type_list<TMessageTypes...>;
#endif
using base_type::base_type; // inherit constructors
};
#else
//*************************************************************************************************
// For C++14 and below.
// For C++03.
//*************************************************************************************************
//***************************************************************************
// The definition for all 16 message types.
@ -2955,7 +3104,7 @@ namespace etl
};
#endif
#if ETL_USING_CPP11 && !defined(ETL_MESSAGE_ROUTER_FORCE_CPP03_IMPLEMENTATION)
#if ETL_USING_CPP17 && !defined(ETL_MESSAGE_ROUTER_FORCE_CPP03_IMPLEMENTATION)
template <typename TDerived, typename... TMessageTypes>
class message_router<TDerived, etl::type_list<TMessageTypes...>>
: public message_router<TDerived, TMessageTypes...>

View File

@ -234,6 +234,7 @@ add_executable(etl_tests
test_message_bus.cpp
test_message_packet.cpp
test_message_router.cpp
test_message_router_with_type_list.cpp
test_message_router_registry.cpp
test_message_timer.cpp
test_message_timer_atomic.cpp
@ -252,6 +253,7 @@ add_executable(etl_tests
test_nth_type.cpp
test_numeric.cpp
test_observer.cpp
test_observer_with_type_list.cpp
test_optional.cpp
test_overload.cpp
test_packet.cpp
@ -370,6 +372,7 @@ add_executable(etl_tests
test_vector_pointer.cpp
test_vector_pointer_external_buffer.cpp
test_visitor.cpp
test_visitor_with_type_list.cpp
test_xor_checksum.cpp
test_xor_rotate_checksum.cpp
)

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,15 @@ namespace
CHECK_TRUE((std::is_same<Data, etl::tuple_element_t<3, Tuple>>::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)
{