我正致力于改进内部消息库,旨在在我们的应用程序内部发送消息,以及外部消费者。邮件由SELECT id_customer FROM customer WHERE id_customer NOT IN (1,2,3,4,5,6,7,8,9) GROUP BY id_customer
(MessageType
)和一些数据(enum class
)组成。每个struct
对应于特定数据类型(例如,MessageType::
将始终包含MessageType::TypeA
)。但是,多种消息类型可以使用相同的结构(例如,Foo
也可以使用MessageType::TypeM
)。
我们有一个可以发送消息的类。我们之前的消息发送者类实现为每种类型定义了一种方法:
Foo
当有大量消息时,这会导致大量代码重复(方法体基本相同,但不同的参数类型除外)。
我实施了一种新方法:
SendMessageTypeA(Foo data)
SendMessageTypeB(Bar data)
SendMessageTypeM(Foo data)
此单一方法可以发送任何消息,具体取决于提供的相应模板参数。请注意,template<typename structType>
void Send(MessageType msgType, const structType & messageData)
始终在编译时已知。
问题是这种新方法不会强制MessageType
和MessageType
之间的关系。例如,struct
将编译,即使Send<Foo>(MessageType::TypeB, data)
应包含MessageType::TypeB
。将在运行时检测到不匹配,但我想使其成为编译时错误。
我不知道如何实现这一目标。我考虑过了:
Bar
方法,并使用它们来调用SendMessageX()
。这确实减少了重复,但每次定义消息时我仍然需要创建一个新方法。Send<MessageX>()
来捕捉不匹配。我不确定如何将static_assert
映射到所需的MessageType
。答案 0 :(得分:2)
如果你可以将枚举提升到编译时常数,那么就可以:
file_out = open('text_mining.xml', 'a') # before
file_out = open('text_mining.xml', 'w') # after
我们可以创建一个类模板,专门针对枚举所期望的每个枚举:
template <MessageType E, class Data>
void Send(Data const& ) { ... }
然后我们可以用它来写那个静态断言:
template <MessageType E> struct expected_type;
template <> struct expected_type<MessageType::TypeA> { using type = Foo; };
template <> struct expected_type<MessageType::TypeB> { using type = Bar; };
template <> struct expected_type<MessageType::TypeM> { using type = Foo; };
template <MessageType E>
using expected_type_t = typename expected_type<E>::type;
或者,可以使用该类模板直接设置template <MessageType E, class Data>
void Send(Data const& ) {
static_assert(std::is_same<Data, expected_type_t<E>>{}, "!");
// ...
}
类型:
Data
答案 1 :(得分:-1)
这是另一个版本,我认为它更清晰,可以在消息和数据之间匹配多种类型。
template<typename MT, typename DT>
struct CompitableCheck;
// only declare type pairs you want. A simple macro wrapping it is better
template<>
struct CompitableCheck<MsgTypeA, Bar> { static const bool value = true; };
template<>
struct CompitableCheck<MsgTypeA, Foo> { static const bool value = true; };
template<> // allow one-to-many map, TypeA -> Foo && TypeA -> Bar.
struct CompitableCheck<MsgTypeA, Bar> { static const bool value = true; };
// here goes the final function
template<typename MT, typename DT,
typename = typename std::enable_if<CompitableCheck<MT, DT>::value>>::type
void Send(MT msgType, const DT & messageData) { /* send it */ }