给定一组类,调用具有匹配方法参数的类

Given a set of classes, call the one with matching method parameters

本文关键字:参数 方法 调用 一组      更新时间:2023-10-16

我有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作为这样的注册表