如何在 C++ 中重载作为参数传递给模板 class 的基 class 方法?

How to overload a method of base class passed as a parameter to a template class in C++?

有两个class:

class A {
public:
    virtual void foo( int bar );
}
class B {
    virtual void foo( string bar, int baz);
}

现在,我正在构建的 class(es) 可以派生自 class。但是有一些通用的辅助代码,所以我想把它分解成一个基数 class。 此公共代码必须从 foo 调用,并且应采用与相应的 foo 方法相同的参数。所以我声明了这个模板 class,但不知道是否可以从模板参数(它是一个基础 class - - AB):

template<class Base>
class CommonBase : public Base {
    public:
        // how do I overload Base::foo here?
        void foo(/*Base::foo arguments here*/) {
            commonCode(/*Base::foo arguments here*/);
        }
    protected:
        // how do I define commonCode with Base::foo signature below?
        void commonCode(/*Base::foo arguments here*/) { ... }
}

我对 C++ 模板没有什么经验,所以想知道——这可能吗? 我看到的一种解决方案是为方法签名添加另一个模板参数,并在专门化时显式传递它。但感觉是多余的,因为 foo 签名的知识已经包含在 Base class 参数中(如果 Base 不提供 foo ,编译应该会失败根本)。

One solution I see is to add another template parameter for method signature and pass it explicitly when specializing.

这是在正确的轨道上,但你不必明确地通过它;您可以从基础 class:

中提取类型
template<class Base, class... Arg>
class CommonBaseImpl : public Base {
    public:
        // how do I overload Base::foo here?
        void foo(Arg... arg) override {
            commonCode(std::forward<Arg>(arg)...);
        }
    protected:
        // how do I define commonCode with Base::foo signature below?
        void commonCode(Arg... arg) { ... }
};

template <class Base, class Foo = decltype(&Base::foo)>
struct BaseSelector;

template <class Base, class... Arg>
struct BaseSelector<Base, void (Base::*)(Arg...)>
{
  using type = CommonBaseImpl<Base, Arg...>;
};

template <class Base>
using CommonBase = typename BaseSelector<Base>::type;

[Live example]

这通过使用 class 模板偏特化分解函数类型来实现。 BaseSelector 的模板参数 Foo 将保存指向 foo 的成员指针的类型。要获得此类型,我们使用 decltype(&Base::foo),该参数的默认参数。

但是,我们需要从该类型中访问各个参数类型。这通常是使用模板部分特化来完成的,就像这里一样。基本上,主要模板说: "This class template takes two types, Base and Foo." 它们是类型,我们对它们一无所知。我们也不将它们用于任何用途(甚至未定义主模板)。

然后,我们提供专业化。这实际上是说:"When the type Foo happens to be a pointer to member function of Base which returns void and takes arguments of type Arg..., then do this: { partially specialised class definition }"。实际上,它只是一种为 pointer-to-member 类型的各个组件分配名称的方法。