2011-09-26 158 views
5

如何編寫在任意類型的任意容器上運行的模板函數?比如我怎麼概括這個虛擬函數模板模板C++函數

template <typename Element> 
void print_size(const std::vector<Element> & a) 
{ 
    cout << a.size() << endl; 
} 

template <template<typename> class Container, typename Element> 
void print_size(const Container<Element> & a) 
{ 
    cout << a.size() << endl; 
} 

這裏是一個典型的使用

std::vector<std::string> f; 
print_size(f) 

這給錯誤

tests/t_distances.cpp:110:12: error: no matching function for call to ‘print(std::vector<std::basic_string<char> >&)’. I'm guessing I must tell the compiler something more specific about what types that are allowed. 

這是什麼調用模板的變種,我該如何解決?

回答

13

是否有特定的原因讓您使用模板模板?爲什麼不只是這樣?

template <typename Container> 
void print_size(Container const& a) 
{ 
    cout << a.size() << endl; 
} 

一般來說,模板模板並不值得麻煩。在你的特定情況下,它們當然沒有用處,如果你確實需要訪問成員類型,我建議你不要屈從於常規做法並使用元函數(在這種情況下爲typename Container::value_type)。

+0

如果您需要獲取「包含」類型,該怎麼辦?就像如果你想創建一個函數,它可以從兩個std :: vector(一個用於鍵,另一個用於值)爲你提供一個std :: map。但是你可以像使用begin()和end()迭代器的自定義類一樣使用std :: vector之外的其他東西。 – ibizaman

+0

@ibizaman這就是typendefs的用途。只需使用'typename Container :: value_type'(注意前綴'typename',這很重要;還有其他問題解釋了原因)。 –

+0

是這個value_type標準嗎?那麼,我知道它是stl :: vector中的stl,但它是自定義類的公認方法嗎? – ibizaman

1

爲什麼曾經使用過類似

template <template<typename> class Container, typename Element> 
void print_size(const Container<Element> & a) 
{ 
    cout << a.size() << endl; 
} 

?用更簡單的方式:

template<typename Container> 
void print_size(const Container & a) 
{ 
    cout << a.size() << endl; 
} 

當調用print_size(f),你會打電話給print_sizeContainervector<string>

3

問題是vector模板需要兩個類型參數,並且您的模板只接受接受單個參數的模板參數。最簡單的辦法是搬起位類型安全的,只是使用Container作爲類型:

template <typename Container> 
void print_size(Container const & c) { 
    std::cout << c.size() << std::endl; 
} 

可能添加靜態檢查(任何類型Container是,它必須有一個value_type嵌套類型,它是Element ... )另一種方法是使模板模板參數匹配要傳遞的模板(包括序列的分配器,關聯容器的分配器和順序謂詞)...

0

對於這些類型的通用算法,I總是喜歡迭代器,即

template <typename IteratorType> 
void print_size(IteratorType begin, IteratorType end) { 
    std::cout << std::distance(begin, end) << std::endl; 
} 

要撥打:

std::vector<std::string> f; 
print_size(f.begin(), f.end()); 
+0

爲什麼你會喜歡這個,尤其是看到'distance'算法的複雜性可能比'size'成員函數更差? – UncleBens

+0

@UncleBens - 是的 - 對於非隨機訪問迭代器是這樣的,在這種情況下 - 應該沒有區別。無論如何,這個例子是微不足道的,我的意思是(大部分)大多數標準庫算法都可以與迭代器一起工作,所以爲什麼不用同樣的方法來做你的算法呢? – Nim

2

我知道這個問題是很久以前問過,但我有同樣的問題,解決的辦法是,你需要寫

template <template <typename,typename> class Container, typename element, typename Allocator> 
void print_size(Container<element, Allocator> & a) 
{ 
    std::cout << a.size() << std::endl; 
} 

因爲矢量有兩個模板參數