mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
Added message type traits
This commit is contained in:
parent
4245e23bee
commit
c6dc700cf3
@ -62,6 +62,8 @@ namespace etl
|
||||
}
|
||||
};
|
||||
|
||||
class message_tag {};
|
||||
|
||||
#if ETL_HAS_VIRTUAL_MESSAGES
|
||||
//***************************************************************************
|
||||
/// Message interface.
|
||||
@ -85,10 +87,14 @@ namespace etl
|
||||
/// Virtual.
|
||||
//***************************************************************************
|
||||
template <etl::message_id_t ID_, typename TBase = etl::imessage>
|
||||
class message : public TBase
|
||||
class message : public TBase, public etl::message_tag
|
||||
{
|
||||
public:
|
||||
|
||||
ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TBase>::value), "TBase is not derived from etl::imessage");
|
||||
|
||||
typedef TBase base_type;
|
||||
|
||||
//***********************************
|
||||
ETL_NODISCARD virtual etl::message_id_t get_message_id() const ETL_NOEXCEPT ETL_OVERRIDE
|
||||
{
|
||||
@ -149,12 +155,14 @@ namespace etl
|
||||
/// Non-virtual.
|
||||
//***************************************************************************
|
||||
template <etl::message_id_t ID_, typename TBase = etl::imessage>
|
||||
class message : public TBase
|
||||
class message : public TBase, public etl::message_tag
|
||||
{
|
||||
public:
|
||||
|
||||
ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TBase>::value), "TBase is not derived from etl::imessage");
|
||||
|
||||
typedef TBase base_type;
|
||||
|
||||
//***********************************
|
||||
message() ETL_NOEXCEPT
|
||||
: TBase(ID)
|
||||
@ -183,6 +191,78 @@ namespace etl
|
||||
//***************************************************************************
|
||||
template <etl::message_id_t ID_, typename TBase>
|
||||
ETL_CONSTANT etl::message_id_t etl::message<ID_, TBase>::ID;
|
||||
|
||||
//***************************************************************************
|
||||
/// Is T an etl::imessage?
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
struct is_imessage : public etl::bool_constant<etl::is_same<etl::imessage, typename etl::remove_cvref<T>::type>::value>
|
||||
{
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Is T ultimately derived from etl::imessage?
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
struct is_message : public etl::bool_constant<etl::is_base_of<etl::imessage, typename etl::remove_cvref<T>::type>::value>
|
||||
{
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Is T derived from etl::message<>
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
struct is_message_type : public etl::bool_constant<etl::is_base_of<etl::message_tag, typename etl::remove_cvref<T>::type>::value>
|
||||
{
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Is T a base of etl::message<T>
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
struct is_message_base : public etl::bool_constant<etl::is_message<T>::value && !is_message_type<T>::value>
|
||||
{
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Is T a user defined base of etl::message<T>
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
struct is_user_message_base : public etl::bool_constant<etl::is_message_base<T>::value && !is_imessage<T>::value>
|
||||
{
|
||||
};
|
||||
|
||||
#if ETL_USING_CPP17
|
||||
//***************************************************************************
|
||||
/// Is T an etl::imessage?
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
inline constexpr bool is_imessage_v = is_imessage<T>::value;
|
||||
|
||||
//***************************************************************************
|
||||
/// Is T ultimately derived from etl::imessage?
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
inline constexpr bool is_message_v = is_message<T>::value;
|
||||
|
||||
//***************************************************************************
|
||||
/// Is T derived from etl::message<>
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
inline constexpr bool is_message_type_v = is_message_type<T>::value;
|
||||
|
||||
//***************************************************************************
|
||||
/// Is T a base of etl::message<T>
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
inline constexpr bool is_message_base_v = is_message_base<T>::value;
|
||||
|
||||
//***************************************************************************
|
||||
/// Is T a user defined base of etl::message<T>
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
inline constexpr bool is_user_message_base_v = is_user_message_base<T>::value;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -76,18 +76,25 @@ 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...>>;
|
||||
using ThisPacketType = 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...>;
|
||||
static constexpr bool IsMessagePacket = etl::is_same_v<remove_cvref_t<T>, ThisPacketType>;
|
||||
|
||||
template <typename T>
|
||||
static constexpr bool IsIMessage = etl::is_same_v<remove_const_t<etl::remove_reference_t<T>>, etl::imessage>;
|
||||
static constexpr bool IsInMessageList = etl::is_one_of_v<etl::remove_cvref_t<T>, TMessageTypes...>;
|
||||
|
||||
template <typename T>
|
||||
static constexpr bool IsIMessage = etl::is_same_v<etl::remove_cvref_t<T>, etl::imessage>;
|
||||
|
||||
template <typename T>
|
||||
static constexpr bool IsDerivedFromIMessage = etl::is_base_of_v<etl::imessage, etl::remove_cvref_t<T>>;
|
||||
|
||||
public:
|
||||
|
||||
//********************************************
|
||||
/// Default constructor
|
||||
//********************************************
|
||||
#include "private/diagnostic_uninitialized_push.h"
|
||||
message_packet()
|
||||
: valid(false)
|
||||
@ -95,7 +102,9 @@ namespace etl
|
||||
}
|
||||
#include "private/diagnostic_pop.h"
|
||||
|
||||
//**********************************************
|
||||
//********************************************
|
||||
/// Copy constructor
|
||||
//********************************************
|
||||
#include "private/diagnostic_uninitialized_push.h"
|
||||
message_packet(const message_packet& other)
|
||||
: valid(other.is_valid())
|
||||
@ -107,7 +116,9 @@ namespace etl
|
||||
}
|
||||
#include "private/diagnostic_pop.h"
|
||||
|
||||
//**********************************************
|
||||
//********************************************
|
||||
/// Move constructor
|
||||
//********************************************
|
||||
#include "private/diagnostic_uninitialized_push.h"
|
||||
message_packet(message_packet&& other)
|
||||
: valid(other.is_valid())
|
||||
@ -119,36 +130,61 @@ namespace etl
|
||||
}
|
||||
#include "private/diagnostic_pop.h"
|
||||
|
||||
#include "private/diagnostic_uninitialized_push.h"
|
||||
//********************************************
|
||||
///
|
||||
//********************************************
|
||||
#include "private/diagnostic_uninitialized_push.h"
|
||||
template <typename T, typename = typename etl::enable_if<IsIMessage<T> || IsInMessageList<T>>::type>
|
||||
explicit message_packet(T&& msg)
|
||||
explicit message_packet(const etl::imessage& msg)
|
||||
: valid(true)
|
||||
{
|
||||
if constexpr (IsIMessage<T>)
|
||||
if (accepts(msg))
|
||||
{
|
||||
if (accepts(msg))
|
||||
{
|
||||
add_new_message(etl::forward<T>(msg));
|
||||
valid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
|
||||
ETL_ASSERT(valid, ETL_ERROR(unhandled_message_exception));
|
||||
}
|
||||
else if constexpr (IsInMessageList<T>)
|
||||
{
|
||||
add_new_message_type<T>(etl::forward<T>(msg));
|
||||
add_new_message(msg);
|
||||
valid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ETL_STATIC_ASSERT(IsInMessageList<T>, "Message not in packet type list");
|
||||
valid = false;
|
||||
}
|
||||
|
||||
ETL_ASSERT(valid, ETL_ERROR(unhandled_message_exception));
|
||||
}
|
||||
#include "private/diagnostic_pop.h"
|
||||
|
||||
#include "private/diagnostic_uninitialized_push.h"
|
||||
//********************************************
|
||||
///
|
||||
//********************************************
|
||||
explicit message_packet(etl::imessage&& msg)
|
||||
: valid(true)
|
||||
{
|
||||
if (accepts(msg))
|
||||
{
|
||||
add_new_message(etl::move(msg));
|
||||
valid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
|
||||
ETL_ASSERT(valid, ETL_ERROR(unhandled_message_exception));
|
||||
}
|
||||
#include "private/diagnostic_pop.h"
|
||||
|
||||
#include "private/diagnostic_uninitialized_push.h"
|
||||
//********************************************
|
||||
/// Enabled for types that are not a message packet or etl::imessage
|
||||
/// Invokes a static assert for types not in the message type list.
|
||||
//********************************************
|
||||
template <typename T, typename = etl::enable_if_t<!IsMessagePacket<T> &&
|
||||
!IsIMessage<T>, int>>
|
||||
explicit message_packet(T&& msg)
|
||||
: valid(true)
|
||||
{
|
||||
ETL_STATIC_ASSERT(IsInMessageList<T>, "Message type not in packet type list");
|
||||
|
||||
add_new_message_type(etl::forward<T>(msg));
|
||||
}
|
||||
#include "private/diagnostic_pop.h"
|
||||
|
||||
@ -250,7 +286,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_t<etl::is_base_of_v<etl::imessage, TMessage>, bool>
|
||||
accepts()
|
||||
{
|
||||
return accepts<TMessage::ID>();
|
||||
@ -258,7 +294,7 @@ namespace etl
|
||||
|
||||
enum
|
||||
{
|
||||
SIZE = etl::largest<TMessageTypes...>::size,
|
||||
SIZE = etl::largest<TMessageTypes...>::size,
|
||||
ALIGNMENT = etl::largest<TMessageTypes...>::alignment
|
||||
};
|
||||
|
||||
@ -308,11 +344,11 @@ namespace etl
|
||||
/// Only enabled for types that are in the typelist.
|
||||
//********************************************
|
||||
template <typename TMessage>
|
||||
etl::enable_if_t<etl::is_one_of_v<etl::remove_const_t<etl::remove_reference_t<TMessage>>, TMessageTypes...>, void>
|
||||
etl::enable_if_t<IsInMessageList<TMessage>>
|
||||
add_new_message_type(TMessage&& msg)
|
||||
{
|
||||
void* p = data;
|
||||
new (p) etl::remove_reference_t<TMessage>((etl::forward<TMessage>(msg)));
|
||||
new (p) etl::remove_cvref_t<TMessage>((etl::forward<TMessage>(msg)));
|
||||
}
|
||||
#include "private/diagnostic_pop.h"
|
||||
|
||||
|
||||
117
test/test_message.cpp
Normal file
117
test/test_message.cpp
Normal file
@ -0,0 +1,117 @@
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2024 John Wellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include "unit_test_framework.h"
|
||||
|
||||
#include "etl/message.h"
|
||||
|
||||
SUITE(test_message)
|
||||
{
|
||||
//*************************************************************************
|
||||
TEST(test_message_traits)
|
||||
{
|
||||
// imessage
|
||||
// ^
|
||||
// MessageBase
|
||||
// ^
|
||||
// etl::message<I, MessageBase>
|
||||
// ^
|
||||
// Message
|
||||
|
||||
// | is_imessage | is_message | is_message_type | is_message_base | is_user_message_base
|
||||
// imessage | T | T | F | T | F
|
||||
// MessageBase | F | T | F | T | T
|
||||
// Message | F | T | T | F | F
|
||||
// int | F | F | F | F | F
|
||||
|
||||
struct MessageBase : public etl::imessage {};
|
||||
struct Message : public etl::message<1, MessageBase> {};
|
||||
|
||||
#if ETL_USING_CPP17
|
||||
// Is an imessage?
|
||||
CHECK_TRUE(etl::is_imessage_v<etl::imessage>);
|
||||
CHECK_FALSE(etl::is_imessage_v<MessageBase>);
|
||||
CHECK_FALSE(etl::is_imessage_v<Message>);
|
||||
CHECK_FALSE(etl::is_imessage_v<int>);
|
||||
|
||||
// Is an imessage, or derived from imessage?
|
||||
CHECK_TRUE(etl::is_message_v<etl::imessage>);
|
||||
CHECK_TRUE(etl::is_message_v<MessageBase>);
|
||||
CHECK_TRUE(etl::is_message_v<Message>);
|
||||
CHECK_FALSE(etl::is_message_v<int>);
|
||||
|
||||
// Is a concrete message?
|
||||
CHECK_FALSE(etl::is_message_type_v<etl::imessage>);
|
||||
CHECK_FALSE(etl::is_message_type_v<MessageBase>);
|
||||
CHECK_TRUE(etl::is_message_type_v<Message>);
|
||||
CHECK_FALSE(etl::is_message_type_v<int>);
|
||||
|
||||
// Is a message base?
|
||||
CHECK_TRUE(etl::is_message_base_v<etl::imessage>);
|
||||
CHECK_TRUE(etl::is_message_base_v<MessageBase>);
|
||||
CHECK_FALSE(etl::is_message_base_v<Message>);
|
||||
CHECK_FALSE(etl::is_message_base_v<int>);
|
||||
|
||||
// Is a user message base?
|
||||
CHECK_FALSE(etl::is_user_message_base_v<etl::imessage>);
|
||||
CHECK_TRUE(etl::is_user_message_base_v<MessageBase>);
|
||||
CHECK_FALSE(etl::is_user_message_base_v<Message>);
|
||||
CHECK_FALSE(etl::is_user_message_base_v<int>);
|
||||
#else
|
||||
// Is an imessage?
|
||||
CHECK_TRUE(etl::is_imessage<etl::imessage>::value);
|
||||
CHECK_FALSE(etl::is_imessage<MessageBase>::value);
|
||||
CHECK_FALSE(etl::is_imessage<Message>::value);
|
||||
CHECK_FALSE(etl::is_imessage<int>::value);
|
||||
|
||||
// Is an imessage, or derived from imessage?
|
||||
CHECK_TRUE(etl::is_message<etl::imessage>::value);
|
||||
CHECK_TRUE(etl::is_message<MessageBase>::value);
|
||||
CHECK_TRUE(etl::is_message<Message>::value);
|
||||
CHECK_FALSE(etl::is_message<int>::value);
|
||||
|
||||
// Is a concrete message?
|
||||
CHECK_FALSE(etl::is_message_type<etl::imessage>::value);
|
||||
CHECK_FALSE(etl::is_message_type<MessageBase>::value);
|
||||
CHECK_TRUE(etl::is_message_type<Message>::value);
|
||||
CHECK_FALSE(etl::is_message_type<int>::value);
|
||||
|
||||
// Is a message base?
|
||||
CHECK_TRUE(etl::is_message_base<etl::imessage>::value);
|
||||
CHECK_TRUE(etl::is_message_base<MessageBase>::value);
|
||||
CHECK_FALSE(etl::is_message_base<Message>::value);
|
||||
CHECK_FALSE(etl::is_message_base<int>::value);
|
||||
|
||||
// Is a user message base?
|
||||
CHECK_TRUE(etl::is_user_message_base<etl::imessage>::value);
|
||||
CHECK_TRUE(etl::is_user_message_base<MessageBase>::value);
|
||||
CHECK_FALSE(etl::is_user_message_base<Message>::value);
|
||||
CHECK_FALSE(etl::is_user_message_base<int>::value);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
@ -220,6 +220,7 @@ namespace
|
||||
|
||||
// Should cause a static assert.
|
||||
//Packet packet4(message4);
|
||||
//Packet packet4((Message4()));
|
||||
|
||||
CHECK_EQUAL(MESSAGE1, packet1.get().get_message_id());
|
||||
CHECK_EQUAL(MESSAGE2, packet2.get().get_message_id());
|
||||
@ -455,7 +456,7 @@ namespace
|
||||
CHECK(Packet::accepts<Message2>());
|
||||
CHECK(Packet::accepts<Message3>());
|
||||
CHECK(!Packet::accepts<Message4>());
|
||||
|
||||
|
||||
// From static message id.
|
||||
CHECK(Packet::accepts<MESSAGE1>());
|
||||
CHECK(Packet::accepts<MESSAGE2>());
|
||||
|
||||
@ -7396,6 +7396,7 @@
|
||||
<ClCompile Include="..\test_macros.cpp" />
|
||||
<ClCompile Include="..\test_math.cpp" />
|
||||
<ClCompile Include="..\test_math_functions.cpp" />
|
||||
<ClCompile Include="..\test_message.cpp" />
|
||||
<ClCompile Include="..\test_message_broker.cpp" />
|
||||
<ClCompile Include="..\test_poly_span_dynamic_extent.cpp" />
|
||||
<ClCompile Include="..\test_poly_span_fixed_extent.cpp" />
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user