2011-02-27 47 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