传递模板原型作为模板参数 - 是否可能?

时间:2015-03-02 10:32:31

标签: c++ templates

首先,为术语道歉 - 我不确定模板原型是否是正确的术语。我的意思是:

template <class T, class X>
class TemplatePrototype
{
 // code
};

我有一种情况,我有一个函数,它根据该函数的模板参数创建一个模板对象。

template <class T, class X>
void doSomething()
{
    TemplatePrototype<T, X> aTemplateTX;
    aTemplateTX.doSomethingElse();
}

然而,大约有15个不同版本的TemplatePrototype,它们都具有相同的接口但执行不同(TemplatePrototype由另一个库提供)。因此,我有很多代码如下:

template <class T, class X>
void doSomethingWithOne()
{
    TemplatePrototypeOne<T, X> aTemplateTX;
    aTemplateTX.doSomethingElse();
}

template <class T, class X>
void doSomethingWithTwo()
{
    TemplatePrototypeTwo<T, X> aTemplateTX;
    aTemplateTX.doSomethingElse();
}

作为架构的结果,我必须知道我将在之前使用的哪个TemplatePrototype我知道实际的类型T和X.我会喜欢看到这样的事情:

template <class T, class X, class Prototype>
void doSomething()
{
    Prototype<T, X> aPrototype;
    aPrototype.doSomething();
}

但我提前指定了部分模板参数 - 即在我知道T和X之前我指定了Prototype。显然,这在C ++中是不可能的。

同样,我无法将Prototype作为模板参数传递,因为它仍会导致大量重复代码。

一些重要事实:我知道所有可能输入的范围。

所以理论上我可以使用宏来定义每个可能的模板特化并将它们插入到容器中,然后我将用它来访问我需要的特化。但是,我正在寻找一个更优雅的&#39;解决方案 - 是否可以传递模板原型而不将它们作为模板类的参数进行专门化,然后在调用函数时进行实例化?例如:

template <class Prototype>
class Holder
{
    template <class T, class X>
    void doSomething()
    {
        Prototype<T, X> aPrototype;
        aPrototype.doSomethingElse();
    }
};

据我所知这是不可能的,但我想知道SO社区是否有一些知道解决方案的人?

编辑:

所以我已经将此作为我的解决方案实现了,感谢下面的答案!

#include <iostream>

template <typename T>
struct Foo
{
        Foo() { aPtr = 0; }
        T* aPtr;
};

template <template<typename> class C>
struct Bar
{
        template <class T>
        void doSomething()
        {
                C<T> aClass;
                if (aClass.aPtr)
                        std::cout << "Hello world" << std::endl;
        }
};


int main()
{
        Bar<Foo> aFoo;
        aFoo.doSomething<int>();

        return 0;
}

这使我能够指定我希望使用哪个TemplatePrototype,之前我可以知道模板参数。

2 个答案:

答案 0 :(得分:4)

是的,使用模板模板参数,例如

template <typename T>
struct Foo
{
};

template <template<typename> class C>
struct Bar
{
};

然后

Bar<Foo> b;

答案 1 :(得分:3)

您正在寻找模板模板参数

在模板参数列表中,而不仅仅是:

class TemplatePrototype

将你的原型指定为一个类模板,它本身有两个模板类型参数(这里没有给它们命名),如:

template<class,class> class TemplatePrototype
//^^^^^^^^^^^^^^^^^^^

这将产生如下函数:

template <class T, class X,
          template<class,class> class TemplatePrototype>
void doSomething()
{
    TemplatePrototype<T, X> aTemplateTX;
    aTemplateTX.doSomethingElse();
}

调用示例:

doSomething<T, X, TemplatePrototypeOne>();

要独立于传递给“原型”的模板参数的数量(此处为2,即TX),您可以使用可变参数模板(自C ++ 11起) )。

为此,首先将原型模板参数移动到第一个位置:

template <template<class,class> class TemplatePrototype,
          class T, class X>

然后,将class T, class X替换为class ...Tsclass,class是任意数量类型参数的占位符。此外,在模板模板参数列表中,将class...替换为<T, X>。在函数实现中的实例化中,将<Ts...>替换为template <template<class...> class TemplatePrototype, class ... Ts> void doSomething() { TemplatePrototype<Ts...> aTemplateTs; aTemplateTs.doSomethingElse(); } 以“扩展”参数包。

结果如下:

{{1}}

Live demo