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_Template Specialization_Partial Specialization - Fatal编程技术网

C++ 函数模板专门化以强制类型为的枚举值

C++ 函数模板专门化以强制类型为的枚举值,c++,templates,template-specialization,partial-specialization,C++,Templates,Template Specialization,Partial Specialization,在给定消息类型和特定于该消息类型的数据结构的情况下,发送消息需要一个函数: enum class MsgType { msgInt, msgDouble, msgString }; template < some template here > void sendMessage(MsgType type, T value); enum类MsgType { msgInt, msgDouble, msgString }; 模板 无效发送消息(MsgType类型

在给定消息类型和特定于该消息类型的数据结构的情况下,发送消息需要一个函数:

enum class MsgType
{
    msgInt,
    msgDouble,
    msgString
};

template < some template here >
void sendMessage(MsgType type, T value);
enum类MsgType
{
msgInt,
msgDouble,
msgString
};
模板<此处的一些模板>
无效发送消息(MsgType类型,T值);
我希望通过以下方式调用此函数:

sendMessage( MsgType::msgInt, 42 );
sendMessage( MsgType::msgString, "Answer to the life, etc,etc.");
//sendMessage( MsgType::msgDouble, "Should not compile");
//sendMessage<MsgType::msgString>( "That is easy!" );
sendMessage(MsgType::msgInt,42);
sendMessage(MsgType::msgString,“生命的答案等”);
//sendMessage(MsgType::msgDouble,“不应编译”);
//sendMessage(“这很简单!”);
如何实现前面描述的模板函数专门化

注意:如果可能,使用C++11,但也可以使用C++14

编辑:

当前实现,它只接受MsgType作为模板参数(而不是函数参数)

模板
无效发送消息(T数据);
templatevoid SendMessage(int数据){/…}
templatevoid SendMessage(int数据){/…}
templatevoid SendMessage(字符串数据){/…}
//电话
发送消息(42);

除非我完全偏离了底线

您可以有三个重载
sendMessage
receiveMessage

void sendMessage(int m);
void sendMessage(double m);
void sendMessage(std::string const& m);

不需要
枚举
或函数模板

更新,回应OP的评论

我的建议是:

  • 创建
    struct
    s以用作标记,而不是
    enum
  • 使用标记
    struct
    s重载
    sendMessage
    receiveMessage

  • 然后使用

    void sendMessage(int_message_t, int m);
    void sendMessage(double_message_t, double m);
    void sendMessage(string_message_t, std::string const& m);
    void sendMessage(username_message_t, std::string const& m);
    void sendMessage(numcars_message_t, int m);
    void sendMessage(bigstruct_message_t, big_struct const& m);
    


    如果您可以使用函数模板来实现这些函数,这将很好,但我仍然将其作为实现细节。

    与其验证用户是否将正确的消息类型枚举值传递到发送函数中,不如使用以下特性完全阻止它:

    #include <iostream>
    
    enum class MsgType
    {
        msgInt,
        msgDouble,
        msgString
    };
    
    template <typename T>
    struct MsgTypeOf;
    
    template <>
    struct MsgTypeOf<int>
    {
        static MsgType msg_type;
    };
    
    template <>
    struct MsgTypeOf<double>
    {
        static MsgType msg_type;
    };
    
    template <>
    struct MsgTypeOf<const char*>
    {
        static MsgType msg_type;
    };
    
    MsgType MsgTypeOf<int>::msg_type = MsgType::msgInt;
    MsgType MsgTypeOf<double>::msg_type = MsgType::msgDouble;
    MsgType MsgTypeOf<const char*>::msg_type = MsgType::msgString;
    
    template <typename T>
    int sendMessage(T value)
    {
        return static_cast<int>(MsgTypeOf<T>::msg_type);
    }
    
    int main()
    {
        std::cout << sendMessage(42) << std::endl;
        std::cout << sendMessage("Answer to the life, etc,etc.") << std::endl;
        std::cout << sendMessage(42.42) << std::endl;
    }
    
    #包括
    枚举类MsgType
    {
    msgInt,
    msgDouble,
    msgString
    };
    模板
    结构MsgTypeOf;
    模板
    结构MsgTypeOf
    {
    静态msg类型msg_类型;
    };
    模板
    结构MsgTypeOf
    {
    静态msg类型msg_类型;
    };
    模板
    结构MsgTypeOf
    {
    静态msg类型msg_类型;
    };
    MsgType MsgTypeOf::msg_type=MsgType::msgInt;
    MsgType MsgTypeOf::msg_type=MsgType::msgDouble;
    MsgType MsgTypeOf::msg_type=MsgType::msgString;
    模板
    int sendMessage(T值)
    {
    返回静态_类型转换(MsgTypeOf::msg_类型);
    }
    int main()
    {
    
    std::cout模板可以具有编译时已知的常量参数。您可以执行以下操作:

    enum MsgType {
        msgInt,
        msgDouble,
        msgString
    };
    
    template<int>
    struct Message { };
    
    template<>
    struct Message<MsgType::msgInt> {
        static void send(int value) { cout << "int: " << value; }
    };
    
    template<>
    struct Message<MsgType::msgDouble> {
        static void send(double value) { cout << "double: " << value; }
    };
    
    template<>
    struct Message<MsgType::msgString> {
        static void send(const char* value) { cout << "string: " << value; }
    };
    
    enum MsgType{
    msgInt,
    msgDouble,
    msgString
    };
    模板
    结构消息{};
    模板
    结构消息{
    
    静态void send(int-value){cout保留您提供的确切方法调用不能在错误的枚举类型上给出编译错误,因为发送的枚举类型仅在运行时(作为方法参数)已知。并且您不能重载函数参数值(仅在类型上)

    将枚举作为模板参数()获取允许在编译时进行检查

    重载类型(和-使用两种不同的方法)也是一个不错的选择


    我相信这是最接近您所要求的。也许您可以为每个
    结构添加一个
    静态常量int值
    ,这样它实际上将被用作
    枚举

    MsgType
    似乎是不必要的。模板专门化是在模板参数上完成的,您可以留给编译器进行推断。大致,应该怎么办?
    sendMessage
    如果有一条sendMessage,另一方面,需要一条receiveMessage,它需要匹配类型。99%的时候信任程序员是好的,但最后1%会让你疯狂调试一整天。
    receiveMessage
    是在同一个过程中吗?是的,整个库都是共享的。但我期待更多的时间“通用”解决方案比针对这种特定情况的技巧更有效。(我的目的是在这里学习)您是否考虑过
    sendMessage
    receiveMessage
    的三个重载?为什么您认为这不能满足您的需要?如果您有多个需要相同类型的MsgType值,该怎么办?@AdrianMail,请详细说明。您的解决方案是一个简单的重载函数:它不保护发送“MsgInt”使用字符串值。如果添加更多MsgType,如“msgNumCars”、“msgUserName”、“msgBigStructure”…此消息与提供的数据类型完全不匹配。+1@AdrianMaire我相信这是最接近您所要求的。也许您可以添加一个
    静态常量int值,每个
    结构都有一个唯一的值,因此它实际上将类似于
    enum
    。非常有趣的代码!!a实际上,您的做法是相反的:不是强制使用数据类型的消息类型,而是从数据类型中获取消息类型。+1@AdrianMail保留您提供的确切方法调用,不能在错误的枚举类型上给出编译错误,因为发送的枚举类型仅在运行时已知(作为方法参数)。您仍然可以使用:
    模板void sendmages(T val){Message::send(val);}
    将@IdanYadgar解决方案转换为全局方法调用,然后调用它:
    sendmages(42);
    sendmages(“生命的答案等”);
    /sendmages(“不应编译”);
    没有办法强制MsgType为constexpr并从中检测模板参数?@AdrianMaire constexpr不允许用于函数参数,因此我无法将其视为constexpr。(如果有一种有趣的方法)C++中的Enums只是整数,因此编译器不能阻止您发送特定整数给接受整数的方法。唯一的方法是模板专用性,它决定了要做什么取决于模板参数,因为模板参数是已知的。
    void sendMessage(int_message_t, int m);
    void sendMessage(double_message_t, double m);
    void sendMessage(string_message_t, std::string const& m);
    void sendMessage(username_message_t, std::string const& m);
    void sendMessage(numcars_message_t, int m);
    void sendMessage(bigstruct_message_t, big_struct const& m);
    
    void receiveMessage(int_message_t, int& m);
    void receiveMessage(double_message_t, double& m);
    void receiveMessage(string_message_t, std::string& m);
    void receiveMessage(username_message_t, std::string& m);
    void receiveMessage(numcars_message_t, int& m);
    void receiveMessage(bigstruct_message_t, big_struct& m);
    
    #include <iostream>
    
    enum class MsgType
    {
        msgInt,
        msgDouble,
        msgString
    };
    
    template <typename T>
    struct MsgTypeOf;
    
    template <>
    struct MsgTypeOf<int>
    {
        static MsgType msg_type;
    };
    
    template <>
    struct MsgTypeOf<double>
    {
        static MsgType msg_type;
    };
    
    template <>
    struct MsgTypeOf<const char*>
    {
        static MsgType msg_type;
    };
    
    MsgType MsgTypeOf<int>::msg_type = MsgType::msgInt;
    MsgType MsgTypeOf<double>::msg_type = MsgType::msgDouble;
    MsgType MsgTypeOf<const char*>::msg_type = MsgType::msgString;
    
    template <typename T>
    int sendMessage(T value)
    {
        return static_cast<int>(MsgTypeOf<T>::msg_type);
    }
    
    int main()
    {
        std::cout << sendMessage(42) << std::endl;
        std::cout << sendMessage("Answer to the life, etc,etc.") << std::endl;
        std::cout << sendMessage(42.42) << std::endl;
    }
    
    enum MsgType {
        msgInt,
        msgDouble,
        msgString
    };
    
    template<int>
    struct Message { };
    
    template<>
    struct Message<MsgType::msgInt> {
        static void send(int value) { cout << "int: " << value; }
    };
    
    template<>
    struct Message<MsgType::msgDouble> {
        static void send(double value) { cout << "double: " << value; }
    };
    
    template<>
    struct Message<MsgType::msgString> {
        static void send(const char* value) { cout << "string: " << value; }
    };
    
    Message<MsgType::msgInt>::send(5);
    Message<MsgType::msgDouble>::send(3.14);
    Message<MsgType::msgString>::send("hello");
    
    // will not compile
    //Message<MsgType::msgDouble>::send("should not compile");
    
    int type = MsgType::msgInt;
    Message<type>::send(123);