2014-01-21 252 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库的容器无关的算法。