我有这个模板功能:
template<int i> void f(int a[i]) { };
int main () {
int c[10];
f(c); // Causes an error!
}
为什么我不能将c[10]
作为非模板类型参数传递给模板函数?
答案 0 :(得分:7)
请记住,看起来像数组的函数参数实际上是指针,因此您的模板实际上等同于
template<int i> void f(int * a);
无法从函数参数中推断出模板参数。您可以明确指定它:
f<10>(c);
但这很容易出错;更好的选择是通过引用传递数组,以便可以推导出模板参数:
template<int i> void f(int (&a)[i]);
或者,在C ++ 11或更高版本中,您可以使用std::array
这是一种合理的对象类型,没有任何内置数组类型的怪癖。
答案 1 :(得分: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
中开发的算法应该与任何提供迭代器的容器一起使用,您还应该考虑使用 iterators :
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库用于其与容器无关的算法。
答案 2 :(得分: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) { };
答案 3 :(得分:2)
不幸的是,当您传递数组时,数组会有效地丢失其大小信息,因此编译器无法从您的调用中推断出i
的值。一个相当不优雅的解决方案是在您的调用中明确指定模板参数,例如:
f<10>(c);
显然,尽管有一个模板,但这几乎无法实现。更好的选择可能是使用std::array
。