所以首先,对术语表示歉意 - 我不确定模板原型是否正确。我的意思是:
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,即 T
和 X
(,您可以使用可变参数模板(自 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();
}
现场演示