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