Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 强制实现模板函数参数之间的所需关系_C++_Templates_C++11 - Fatal编程技术网

C++ 强制实现模板函数参数之间的所需关系

C++ 强制实现模板函数参数之间的所需关系,c++,templates,c++11,C++,Templates,C++11,我正在努力改进一个内部消息传递库,该库设计用于在我们的应用程序内部以及向外部消费者发送消息。消息由MessageType(enum class)和一些数据(struct)组成。每个MessageType::对应于特定的数据类型(例如,MessageType::TypeA将始终包含Foo)。但是,多个消息类型可以使用同一个结构(例如,MessageType::TypeM也可以使用Foo) 我们有一个可以发送消息的类。我们以前的message sender类实现为每种类型定义了一个方法: SendM

我正在努力改进一个内部消息传递库,该库设计用于在我们的应用程序内部以及向外部消费者发送消息。消息由
MessageType
enum class
)和一些数据(
struct
)组成。每个
MessageType::
对应于特定的数据类型(例如,
MessageType::TypeA
将始终包含
Foo
)。但是,多个消息类型可以使用同一个结构(例如,
MessageType::TypeM
也可以使用
Foo

我们有一个可以发送消息的类。我们以前的message sender类实现为每种类型定义了一个方法:

SendMessageTypeA(Foo data)
SendMessageTypeB(Bar data)
SendMessageTypeM(Foo data)
当存在大量消息时,这可能会导致大量代码重复(方法体基本相同,不同的参数类型除外)

我实现了一种新方法:

template<typename structType>
void Send(MessageType msgType, const structType & messageData)
模板
void Send(MessageType msgType、const structType和messageData)
此单一方法可以发送任何消息,具体取决于所提供的适当模板参数。请注意,
MessageType
在编译时总是已知的

问题在于,这种新方法没有强制执行
MessageType
struct
之间的关系。例如,
Send(MessageType::TypeB,data)
将被编译,即使
MessageType::TypeB
应该包含
Bar
。不匹配将在运行时检测到,但我想将其设置为编译时错误

我不知道如何才能做到这一点。我考虑过:

  • 声明所有
    SendMessageX()
    方法,并使用它们调用
    Send()
    。这确实减少了重复,但我仍然必须在每次定义消息时创建一个新方法
  • 试图使用
    static\u assert
    捕获不匹配。我不知道如何将
    MessageType
    s映射到所需的
    struct
  • 我找错人了

  • 如果可以将枚举提升到编译时常量,则可以:

    template <MessageType E, class Data>
    void Send(Data const& ) { ... }
    

    这里是另一个版本,我认为它更清晰,可以匹配消息和数据之间的多种类型

    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 */ }
    
    模板
    结构完整性检查;
    //仅声明所需的类型对。一个简单的宏包装它更好
    模板
    结构CompitableCheck{static const bool value=true;};
    模板
    结构CompitableCheck{static const bool value=true;};
    模板//允许一对多映射,TypeA->Foo&&TypeA->Bar。
    结构CompitableCheck{static const bool value=true;};
    //这是最后一个函数
    模板::类型
    void Send(MT msgType、const DT和messageData){/*发送它*/}
    
    您知道编译时的消息枚举吗?是的,关联在编译时是已知的,而不是您调用的
    Send()
    值。是的,我知道编译时发送的每个消息的类型我的意思是。。。您是否总是可以调用
    Send(data)
    ?请原谅我的无知,但是“将枚举提升到编译时常量”是什么意思?这意味着可以在运行时定义枚举。如何工作?@Michael枚举值可以在运行时确定。不过,我们在编译时需要它。您应该将最后一个代码段上的省略号转换为注释,以保持与前一个代码段的一致性。这种方法工作得很好,因为预期类型在其他情况下可用于确定数据类型。
    template <MessageType E, class Data>
    void Send(Data const& ) {
        static_assert(std::is_same<Data, expected_type_t<E>>{}, "!");
        // ...
    }
    
    template <MessageType E>
    void Send(expected_type_t<E> const& ) {
        ...
    }
    
    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 */ }