实现模板化模板方法

Nic*_*ler 3 c++ templates design-patterns template-method-pattern

注意:以下问题与模板方法设计模式C ++函数模板有关。为了区分两者,在引用设计模式时将使用斜体,在引用C ++模板时将使用粗体

模板方法模式的思想是使算法的各个部分可互换。这通常是通过继承来实现的,子类提供了具体的实现,这些实现被插入到基类的算法中。但是,如果挂钩方法需要为template,则此方法将无法工作,因为模板不能是虚拟的。这是一个不编译的简单示例:

class Base
{
public:

    // This is the template method
    template <typename T>
    void doSomething(T input)
    {
        //...
        auto converted = ConvertInput(input);
        //...
        std::cout << converted;
    }

protected:
    //compile error "member function templates cannot be virtual"
    template <typename T>
    virtual T ConvertInput(T input) = 0;
};

class Derived : public Base
{
protected:
    template <typename T>
    T ConvertInput(T input)
    {
        return 2 * input;
    }
};

int main()
{
    Derived d;
    d.doSomething(3);
}
Run Code Online (Sandbox Code Playgroud)

有没有一种方法可以实现使用功能模板挂钩的模板方法

我对将Base类用作任何类型的类型不感兴趣。我将始终使用具体的具体类型来实现最大的编译时优化。因此,此问题的另一种表述是:如何创建几个Derived-1 .. Derived-n具有函数模板的类,这些函数模板在各个实现之间共享一个公共代码框架?

krz*_*zaq 5

听起来像是CRTP的一个好用例。定义Base为一个类模板,并将派生自该模板的类型作为模板参数。在Base的方法中,您可以转换为派生类型:

template<typename Derived>
struct Base
{
    // This is the template method
    template <typename T>
    void doSomething(T input)
    {
        //...
        auto converted = static_cast<Derived*>(this)->ConvertInput(input);
        //...
        std::cout << converted << std::endl;
    }
};
Run Code Online (Sandbox Code Playgroud)

然后定义派生类型,例如:

struct Square : Base<Square>
{
    template<typename T>
    auto ConvertInput(T t)
    {
        return t*t;
    }
};

struct Sum : Base<Sum>
{
    template<typename T>
    auto ConvertInput(T t)
    {
        return t+t;
    }
};
Run Code Online (Sandbox Code Playgroud)

用法很简单:

Square sq;
Sum sum;
sq.doSomething(3);
sum.doSomething(3);
Run Code Online (Sandbox Code Playgroud)

现场演示