2014-01-21 250 views
4

我有這樣的模板函數:非模板類型參數

template<int i> void f(int a[i]) { }; 

int main() { 
    int c[10]; 
    f(c); // Causes an error! 
} 

爲什麼不能我通過c[10]作爲非模板類​​型參數模板功能?

+2

你可以,只是參數'int a [i]'衰變成指針,實際上失去了它的大小信息。因此,當您調用該函數時,「i」不會被推導出來。如果你像'f <10>(c)'那樣調用這個函數,它就會起作用。 – 0x499602D2

回答

7

記住,看起來像一個數組的函數參數實際上是一個指針,所以你的模板實際上是等同於

template<int i> void f(int * a); 

沒有辦法推斷出函數參數模板參數。你可以明確地指定它:

f<10>(c); 

但這很容易出錯;一個更好的選擇是通過參考數組傳遞,從而使模板參數可推導出:

template<int i> void f(int (&a)[i]); 

替代地,在C++ 11或更高,則可以使用std::array這是一個合理的對象類型與無的內置數組類型的怪癖。

5

的原型應該是:

template<std::size_t N> void f(int (&a)[N]) { }; 

注意(&a)語法。

void f(int a[N])衰變到void f(int* a),我們不能推導出模板N

std::array語法看起來更好:

template<std::size_t N> void f(std::array<int, N>& a) { }; 
2

不幸的是陣列有效地失去它們的大小信息,當您通過他們,所以編譯器不能從您的通話推斷的i值。一個頗爲不雅的解決辦法是顯式地指定模板參數在您的呼叫,例如:

f<10>(c); 

顯然是非常失敗,雖然具有模板的點。更好的選擇可能是使用std::array

6

其實正確的函數模板將使用std::size_t作爲模板參數:

template<std::size_t i> void f(int (&a)[i]) 

但使用std::array可能是更好:

template<std::size_t i> void f(const std::array<int, i>&) 

你也應該考慮使用迭代,如果算法您正在開發的f應該與任何提供迭代器的容器一起工作:

template<class It> void f(It begin, It end) 

,讓您可以使用您的功能如下:

int x[10]    = ...; 
std::vector<int> y  = ...; 
std::array<int, 10> z = ...; 

f(std::begin(x), std::end(x)); 
f(std::begin(y), std::end(y)); 
f(std::begin(z), std::end(z)); 

後者通常使用的STL庫的容器無關的算法。