通用代码很好。
- 创建两个转换方法,一个从
TBuffer
到XArgs
,另一个从XResult
到TBuffer
- 创建自动命令包装器
- 实现一个
map
自动分派给那些包装器
您可以通过指向函数的指针或继承来做到这一点,我想继承会更容易......
class BaseCommand {
public:
virtual ~BaseCommand() {}
virtual TBuffer invoke(TBuffer const& tb) = 0;
};
template <typename Args, typename Result>
class CommandT: public BaseCommand {
public:
virtual TBuffer invoke(TBuffer const& tb) {
Args const a = from_buffer(tb, &a); // free function
Result const r = this->invoke(a);
return to_buffer(r); // free function
}
private:
virtual Result invoke(Args const&) = 0;
};
注意:作为作弊,我们通过&a
来from_buffer
获得自动参数推导,预计指针未使用。
所以,让我们假设我们有我们的论点和结果(两者都int
更容易):
int from_buffer(TBuffer const& tb, int const*) {
return tb.asInt();
}
TBuffer to_buffer(int i) {
return TBuffer(i);
}
然后我们可以实现一个处理的命令int
:
class IntCommand: public CommandT<int, int> {
virtual int invoke(int const& i) override { return i; }
};
好的,让我们继续进行调度。这个想法是将每个命令注册到它的 ID。
template <typename T>
std::unique_ptr<BaseCommand> make_command() { return std::unique_ptr<T>(new T()); }
static std::map<int, std::unique_ptr<BaseCommand>> Commands;
int main() {
Commands.insert(std::make_pair(1, make_command<IntCommand>()));
// lots of them...
// starts processing
}
SocketHandler
我们有:
void SocketHandler::ReceiveCommand(int code, TBuffer const& a, TBuffer& r) {
typedef std::map<int, std::unique_ptr<BaseCommand>>::const_iterator const_it;
const_it it = Commands.find(code);
if (it == Commands.end()) {
std::cerr << "Unknown command: " << code << "\n";
throw std::runtime_error("Unknown command");
}
r = it->second->invoke(a);
}