问候。
我不太清楚如何解释自己,但我相信一段代码会让你理解我想要做的事情:
template<class A, class B>
void myFunction(A<B>& list)
{
typename A<B>::iterator current = list.begin();
typename A<B>::iterator end = list.end();
while (current != end)
{
current++;
}
}
其中A是STL容器(vector,list ...)。它就像开始一样,但有模板:模板,模板内等......
问题是:当你的模板的一个参数本身就是一个模板时,你会怎么做......并且仍然希望支持这个模板支持的每种类型。
这当然不能编译(它说“A不是模板”)。
有人知道如何创建这样的模板吗?
答案 0 :(得分:7)
您正在寻找模板模板参数
template<template<class T, class All = std::allocator<T> > class A, class B>
void myFunction(A<B>& list)
{
typename A<B>::iterator current = list.begin();
typename A<B>::iterator end = list.end();
while (current != end)
{
current++;
}
}
但是,在您的特定情况下,我认为通过传递实例化的容器会更好,也就是说,
template<class C>
void myFunction(C& list)
{
...
}
像这样使用
vector<char> v;
myFunction(v);
您的原始代码必须像这样调用:
myFunction<std::vector, char> (v)
更冗长,没有特别的好处
答案 1 :(得分:2)
A
和B
将是具体类型(而不是模板),因此A<B>
毫无意义。
您可以这样编写代码:
template<class List>
void myFunction(List &list)
{
typename List::iterator current = list.begin();
typename List::iterator end = list.end();
while (current != end)
{
current++;
}
}
如果您需要知道该列表中元素的类型,列表中有一个typedef:
typename List::value_type
答案 2 :(得分:-1)
vector<int>
是一个类,因此,您不需要在原型中声明A<B>
。你可以这样做:
template<class A>
void myFunction(A& list)
{
typedef typename A::value_type B; //do this if you need to know the type of the elements.
typename A::iterator current = list.begin();
typename A::iterator end = list.end();
while (current != end)
{
current++;
}
}
但是如果你真的需要,你也可以将模板参数声明为模板:
template< template<class> class A, class B >
void myFunction(A<B>& list)
{
typename A<B>::iterator current = list.begin();
typename A<B>::iterator end = list.end();
while (current != end)
{
current++;
}
}
但上面并不是真的推荐,大多数类模板都有一组嵌套的typedef(比如STL容器中的iterator和value_type),这样你就可以访问了你需要的关于类型的所有信息,而不必使用这些模板模板参数。因此,第一种方法通常是首选和更常规的方法(使它工作通常也不那么麻烦,即编译器倾向于“不喜欢”模板模板参数)。
此外,您无法使用模板模板参数非常轻松地使用STL容器,因为STL容器都具有这些“隐藏”模板参数(例如“allocator”和“compare”用于已排序的容器)。所以,你必须列出所有这些,否则编译器将无法进行匹配。然后,你将没有一个非常“通用”的功能,因为你将不得不假设过去的STL容器,它只会提供一种或两种类型的容器。使用第一种方式真的更好。