给定一组类,调用匹配方法参数的一个 [英] Given a set of classes, call the one with matching method parameters

查看:117
本文介绍了给定一组类,调用匹配方法参数的一个的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个或更多的类继承自单亲。它们都有重载的 handle 方法,但是每个类的句柄方法都有不同的参数。

I have 2 or more classes which inherit from a single parent. They all have overloaded handle methods, but each class has different parameters for their handle methods.

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;

我想要一个函数来评估哪些类具有正确的签名并调用它。这是可能吗?

I want a function that would assess which of the Classes have the right signature and call it. Is this possible?

理想情况下,这将在编译时完成,并且static_assert只有一个匹配。

Ideally, this would be done at compile time, and it would static_assert that there is exactly one match.

给定签名模板< typename C> string sendCommand(C c)

sendCommand< BarCommand>(c)调用 barHandler.handle(c)

sendCommand< FooCommand>(c) code>会调用 fooHandler.handle(c)

推荐答案

通用函数重载将适用于您的情况。您要求签名 template< typename C> string sendCommand(C c)因此模板参数是第一个函数参数的类型。然后只需定义:

Usual function overloading will work for your case. You ask for signature template<typename C> string sendCommand(C c) So template argument is a type of first function argument. Then just define:

string sendCommand(const FooCommand& c) {
    fooHandler.handle(c);
}
string sendCommand(const BarCommand& c) {
    barHandler.handle(c);
}

如果你有很多命令和处理程序,你可以尝试这样:

If you have a lot of commands and handlers you can try this:

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

Note that you need a sort of registry which holds all the handlers. Here I use std::tuple as such registry.

这篇关于给定一组类,调用匹配方法参数的一个的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆