我有 2 个或更多类继承自一个父类。他们都重载了handle
方法,但每个类的句柄方法都有不同的参数。
class CommandHandler {};
class FooCommandHandler : public CommandHandler
{
public:
string handle(const FooCommand& c) { return c.getStringSomehow(); }
};
class BarCommandHandler : public CommandHandler
{
public:
string handle(const BarCommand& c) { return c.getStringSomeOtherWay(); }
string handle(const OtherBarCommand& c) { return c.youGetThePicture(); }
};
FooCommandHandler fooHandler;
BarCommandHandler barHandler;
我想要一个函数来评估哪些类具有正确的签名并调用它。这可能吗?
理想情况下,这将在编译时完成,并且它会 static_assert 恰好有一个匹配项。
给定签名template<typename C> string sendCommand(C c)
:
sendCommand<BarCommand>(c)
会调用barHandler.handle(c)
sendCommand<FooCommand>(c)
会调用fooHandler.handle(c)
最佳答案
通常的函数重载适用于您的情况。你要签名template<typename C> string sendCommand(C c)
所以模板参数是第一个函数参数的一种。然后定义:
string sendCommand(const FooCommand& c) {
fooHandler.handle(c);
}
string sendCommand(const BarCommand& c) {
barHandler.handle(c);
}
然后调用他们。此处甚至不需要模板。
如果你有很多命令和处理程序,你可以试试这个:
// We need a way to retrive handler by its type. Tuple is good for that.
std::tuple<FooCommandHandler, BarCommandHandler> handlers;
// Note the return type. If Handler on position handlerIndex does not have proper method, then instantiation will fail and, due to SFINAE, this function will just be ignored.
template<class Command, size_t handlerIndex = 0>
auto sendCommand(const Command& c) -> decltype(std::get<handlerIndex>(handlers).handle(c))
{
return std::get<handlerIndex>(handlers).handle(c);
}
// Again, SFINAE technique. Compiler will stop search if the template above has been instantiated and will ignore this one. But in other case this template will be used and it will try to call next handler.
template<class Command, size_t handlerIndex>
std::string sendCommand(const Command& c)
{
return sendCommand<Command, handlerIndex + 1>()(c);
}
请注意,您需要一种包含所有处理程序的注册表。在这里,我使用 std::tuple 作为这样的注册表。
关于c++ - 给定一组类,调用具有匹配方法参数的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39805508/