2017-06-20 85 views
2

我有類似下面一個很簡單的測試程序:C++:爲什麼模板不能用於推導容器和元素類型?

#include<vector> 
#include<iostream> 
using namespace std; 
template<typename C, typename E> 
void f(const C<E>& container){ 
    cout<<container.size()<<endl; 
} 
int main(){ 
    vector<int> i; 
    f(i); 
    return 0; 
} 

它無法用gcc 4.1.2編譯。錯誤信息:

templateContainer.cpp:5: error: ‘C’ is not a template 
templateContainer.cpp: In function ‘int main()’: 
templateContainer.cpp:10: error: no matching function for call to ‘f(std::vector<int, std::allocator<int> >&)’ 
+1

這就是爲什麼容器有*關聯類型*。你不需要'E';只需編寫'typename C :: value_type'(或者'typename C :: reference_type')。 –

+0

爲了澄清,錯誤信息是因爲'C'被**定義**爲一個類型的名字('typename C'),但它被**用作**模板的名字('C ') 。它不能兼而有之。 –

回答

9

你可以使用一個模板的模板參數(請注意,std::vector其實需要一個以上的模板參數族的元素類型和分配器類型]):

template<template <typename...> class C, typename... E> 
void f(const C<E...>& container){ 
    cout<<container.size()<<endl; 
} 

Live Demo


如果您不需要類型分解,你可以簡單地使用一個O rdinary模板。

template<typename C> 
void f(const C& container){ 
    cout<<container.size()<<endl; 
} 

你還可以從STL容器獲得的typedef:例如,如果你想知道類型由容器保存元素value_type是有你。

template<typename C> 
void f(const C& container){ 
    using ValueType = typename C::value_type; 
    cout<<container.size()<<endl; 
} 
+0

沒有可變參數模板(即C++ 11),需要事先知道參數的數量? – user463035818

+0

@ tobi303,是的,否則,一些舊的令人不愉快的重載許多模板參數的技巧 – WhiZTiM

+2

請注意,雖然這是絕對正確的答案,如上所述的問題,如果你真的用它來推斷容器的值類型,你應該得到當場被解僱。容器具有關聯類型的typedef,你應該總是使用這些。因爲容器契約需要這些,並且不*要求值類型完全成爲模板參數。 –

1

std :: vector有兩個模板參數,type和allocator。

template <template<class, class> class C, class E, class A> 
void f(const C<E, A> &container) 
{ 
    std::cout << container.size() << endl; 
} 

int main() 
{ 
    std::vector<int> i; 
    f(i); 
    return 0; 
} 
1

雖然WhiZTiM的答案是正確的(當然,更喜歡第二部分),它沒有解釋爲什麼代碼不起作用。

假設爲您打算大致

template<template <typename> class C, typename E> void f(const C<E>&); 

std::vector不匹配的原因,那一刻是,它是錯誤的外形 - 它有兩個類型參數,而不是一個在你的聲明。

僅僅因爲你不經常明確寫入默認的第二個(分配器)參數,並不意味着它不存在。

爲了比較,這個工作(或沒有)以類似的方式:

void f(int); 
void g(int, int* = nullptr); 

void apply(void (*func)(int), int); 

apply(f, 42); // ok - f matches shape void(*)(int) 
apply(g, 42); // error - g is really void(*)(int,int*) 

具體而言,默認參數(或參數類型)是語法糖。它們允許您在調用(實例化)站點處忘記這些參數,但不要更改函數(或模板)的形狀。

相關問題