2011-02-27 39 views
6

问候。模板方法中的std容器

我不很清楚如何解释自己,但我相信一段代码会让你明白我的intenting做:

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容器(矢量,列表...)。这就像开始,但与模板:一个模板,模板内,等...

事情是:你做什么时,你的模板的参数之一本身是一个模板...并仍然希望支持此模板支持的每种类型。

这当然不会编译(它说'A不是模板')。

有人知道如何创建这样的模板吗?

回答

2

AB将是具体类型(而不是模板),因此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 
+1

+1,因为它是解决这一问题的最简单的解决方案。模板模板参数很快就会变得混乱,因为它们需要参数匹配。 – 2011-02-27 19:58:34

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

然而,在特定情况下,第I次墨你会被刚好路过intantiated容器,也就是更好,

template<class C> 
void myFunction(C& list) 
{ 
    ... 
} 

使用这样

vector<char> v; 
myFunction(v); 

你的原代码必须这样调用:

myFunction<std::vector, char> (v) 

这是更详细和没有特别的好处

+0

您不能在模板模板参数中使用默认模板参数,另外,根本不能在函数模板中使用默认模板参数。所以,模板模板参数版本必须针对不同的容器和不同的默认模板参数有几个重载版本,这就是为什么它不是真的可行。 – 2011-02-27 19:24:31

+0

@Mikael:我没有在函数模板中使用默认参数。默认参数是模板的模板参数本身,这是完全合法的 – 2011-02-27 19:26:38

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

但上面的并不推荐使用,最类模板有一组嵌套类型定义(如STL容器中的iterator和value_type),以便您可以访问所需的所有类型信息,而无需使用这些模板模板参数。所以,第一种方法通常是更好的方法,也是更常用的方式(它通常使麻烦变得更简单,即编译器倾向于“不喜欢”模板​​模板参数)。

此外,您不能很容易与模板的模板参数使用STL容器,因为STL容器都有这些“隐藏”的模板参数(例如,“分配”和“比较”的有序容器)。所以,你必须列出所有这些,否则编译器将无法进行匹配。然后,你将不会有一个非常“通用”的功能,因为你将不得不假设已经过去的STL容器,它只能提供一种或两种类型的容器。使用第一种方法真的更好。

+1

你不能传递一个STL容器这种方法,因为STL容器至少有2个模板参数 – 2011-02-27 19:16:39

+0

@Armen的,这是正确的,谢谢指点出来。 – 2011-02-27 19:18:13