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



所以首先,对术语表示歉意 - 我不确定模板原型是否正确。我的意思是:

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();
}

作为体系结构的结果,在我知道实际类型T和X之前,我必须知道我将要使用哪个TemplatePrototype。我想看到这样的东西:

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

但是我事先指定了部分模板参数 - 即我在知道 T 和 X 之前指定了原型C++。

同样,我不能将原型作为模板参数传递,因为它仍然会导致大量重复代码。

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

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

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;
}

这使我能够在知道模板参数之前指定要使用的模板原型。

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

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

然后

Bar<Foo> b;

您正在寻找模板模板参数

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

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 ...Ts ,后者是任意数量的类型参数的占位符。此外,在模板模板参数列表中,将class,class替换为 class... 。在函数实现中的实例化中,将<T, X>替换为<Ts...>以"扩展"参数包。

结果如下所示:

template <template<class...> class TemplatePrototype,
          class ... Ts>
void doSomething()
{
    TemplatePrototype<Ts...> aTemplateTs;
    aTemplateTs.doSomethingElse();
}

现场演示

最新更新