简体   繁体   English

函数模板特化以强制枚举值与类型

[英]Function template specialization to force enum value with type

A function is required to send messages, given a message type and a data structure of a type specific to the message type: 在给定消息类型和特定于消息类型的类型的数据结构的情况下,需要一个函数来发送消息:

enum class MsgType
{
    msgInt,
    msgDouble,
    msgString
};

template < some template here >
void sendMessage(MsgType type, T value);

I expect to call this function in the following way: 我希望以下列方式调用此函数:

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!" );

How could I implement the previously described template function specialization? 我怎样才能实现前面描述的模板功能专业化?

Note: If possible, with C++11, but C++14 is also acceptable. 注意:如果可能,使用C ++ 11,但C ++ 14也是可以接受的。

EDITED: 编辑:

The current implementation, which only accept the MsgType as template parameter (not as function parameter). 当前实现,它只接受MsgType作为模板参数(而不是函数参数)。

template<MsgType Id, typename T>
void sendMessage(T data);

template<>void sendMesssage<MsgType::msgNumCar, int>( int data ){ //...   }
template<>void sendMesssage<MsgType::msgInt, int>( int data ){ //...   }
template<>void sendMesssage<MsgType::msgString, string>( string data ){ //...   }
// A call
sendMessage<MsgType::msgNumCar>( 42 );

Templates can have constant parameters which are known in compile-time. 模板可以具有编译时已知的常量参数。 You could do the following: 您可以执行以下操作:

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; }
};

And invoke it: 并调用它:

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");

notice that the template parameter must be a constant (ie known at compile time). 请注意,模板参数必须是常量(即在编译时已知)。 Which means that the following code won't compile: 这意味着以下代码将无法编译:

int type = MsgType::msgInt;
Message<type>::send(123);

But, why won't you just create 3 overloads for sendMessage ? 但是,为什么不为sendMessage创建3个重载?

Instead of validating that the user passes the correct message type enum value into the send function, prevent it entirely with some traits: 而不是验证用户将正确的消息类型枚举值传递到send函数,而是完全使用某些特征来防止它:

#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;
}

Output: 0 2 1 输出:0 2 1

Unless I am totally off base... 除非我完全偏离基地......

You can have three overloads of sendMessage and receiveMessage . 您可以有三个sendMessagereceiveMessage重载。

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

and

void receiveMessage(int& m);
void receiveMessage(double& m);
void receiveMessage(std::string& m);

There is no need for an enum or a function template. 不需要enum或功能模板。

Update, in response to OP's comment 更新,以回应OP的评论

My suggestion: 我的建议:

  1. Create struct s to be used as tags instead of an enum . 创建struct s到被用作标签,而不是一个enum
  2. Overload sendMessage and receiveMessage using the tag struct s. 使用标记struct s重载sendMessagereceiveMessage

struct int_message_t {};
struct double_message_t {};
struct string_message_t {};
struct username_message_t {};
struct numcars_message_t {};
struct bigstruct_message_t {};

And then overload them using 然后使用它们重载它们

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);

and

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);

If you can use a function template to make the implementations of these functions, that will be nice but I would still leave that as an implementation detail. 如果您可以使用函数模板来实现这些函数的实现,那将会很好,但我仍然会将其作为实现细节。

Preserving the exact method call you presented cannot give compilation error on the wrong enum type, as the enum type sent is known only at runtime (as a method argument). 保留您提供的确切方法调用不能在错误的枚举类型上给出编译错误,因为发送的枚举类型仅在运行时已知(作为方法参数)。 And you cannot overload on function parameter value (only on type). 并且您不能在函数参数值上重载(仅在类型上)。

Getting the enum as a template parameter ( @IdanYadgar ) allows check at compile time. 将枚举作为模板参数( @IdanYadgar )可以在编译时进行检查。

Overloading on type ( @MarkB and @RSahu - using two different approaches) is also a nice option. 类型重载( @MarkB@RSahu - 使用两种不同的方法)也是一个不错的选择。

I believe @RSahu is the closest you can get to what you asked for. 我相信@RSahu是你能得到的最接近你所要求的。 Maybe you can add a static const int value for each struct so it will actually be used as enum . 也许你可以为每个struct添加一个static const int value ,因此它实际上将用作enum

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM