根据数据包类型改变行为,避免 switch 语句
Changing behaviour depending on packet type, avoiding switch statements
我正在编写一个主要通过数据包进行通信的服务器-客户端架构程序。我很难想出一个更 eloquent 的方法来实现这个目标。
这是我目前拥有的东西:
namespace Packet {
enum class TCP {
PLAYER_JOINED,
PLAYER_QUIT,
MESSAGE_SENT
};
}
与这些函数一起将类型转换为整数代码,反之亦然:
constexpr auto toInt(Packet::TCP _t) {
return static_cast<std::underlying_type_t<Packet::TCP>>(_t);
}
constexpr Packet::TCP toTCPType(int _i) {
return static_cast<Packet::TCP>(_i);
}
在我的网络管理器代码中,我目前有一个我想避免的难看的 switch 语句。而不是像现在这样:
void sendPacket(Packet::TCP _type) {
int code{Packet::toInt(_type);
Packet p;
p << code;
switch (_type) {
case Packet::TCP::PLAYER_JOINED:
//do stuff and operate on p
break;
case Packet::TCP::PLAYER_QUIT:
//do stuff and operate on p
break;
//etc.
}
}
如果可以这样的话我会更喜欢:
void preparePacket(Packet::TCP _type) {
//common behaviour that has to be done no matter the type
int code{Packet::toInt(_type);
Packet p;
p << code;
sendPacket(_type, p);
}
不过,我 运行 遇到了一些障碍。显然我不能在 TCP 枚举的值上重载 sendPacket。我可以让每个枚举器类型都有自己的结构,但是我失去了将数据包快速转换为 int 的能力,这对于接收方了解它是什么类型的数据包至关重要。这可以通过添加一个虚拟 getId() 函数来解决,但这只是一种单向转换(Packet 到 int),而我还需要以某种方式从 int 转换为 Packet。
您可以创建一个 std::functions 的向量并使用 _type 作为索引。每个索引处都是处理该特定类型数据包的函数。那么您的代码可能如下所示:
std::vector<std::function<void(Packet)>> handlers = {
player_joined_handler,
player_quit_handler,
message_sent_handler,
}
然后你可以用这个代替开关:
handlers[code](p);
我正在编写一个主要通过数据包进行通信的服务器-客户端架构程序。我很难想出一个更 eloquent 的方法来实现这个目标。
这是我目前拥有的东西:
namespace Packet {
enum class TCP {
PLAYER_JOINED,
PLAYER_QUIT,
MESSAGE_SENT
};
}
与这些函数一起将类型转换为整数代码,反之亦然:
constexpr auto toInt(Packet::TCP _t) {
return static_cast<std::underlying_type_t<Packet::TCP>>(_t);
}
constexpr Packet::TCP toTCPType(int _i) {
return static_cast<Packet::TCP>(_i);
}
在我的网络管理器代码中,我目前有一个我想避免的难看的 switch 语句。而不是像现在这样:
void sendPacket(Packet::TCP _type) {
int code{Packet::toInt(_type);
Packet p;
p << code;
switch (_type) {
case Packet::TCP::PLAYER_JOINED:
//do stuff and operate on p
break;
case Packet::TCP::PLAYER_QUIT:
//do stuff and operate on p
break;
//etc.
}
}
如果可以这样的话我会更喜欢:
void preparePacket(Packet::TCP _type) {
//common behaviour that has to be done no matter the type
int code{Packet::toInt(_type);
Packet p;
p << code;
sendPacket(_type, p);
}
不过,我 运行 遇到了一些障碍。显然我不能在 TCP 枚举的值上重载 sendPacket。我可以让每个枚举器类型都有自己的结构,但是我失去了将数据包快速转换为 int 的能力,这对于接收方了解它是什么类型的数据包至关重要。这可以通过添加一个虚拟 getId() 函数来解决,但这只是一种单向转换(Packet 到 int),而我还需要以某种方式从 int 转换为 Packet。
您可以创建一个 std::functions 的向量并使用 _type 作为索引。每个索引处都是处理该特定类型数据包的函数。那么您的代码可能如下所示:
std::vector<std::function<void(Packet)>> handlers = {
player_joined_handler,
player_quit_handler,
message_sent_handler,
}
然后你可以用这个代替开关:
handlers[code](p);