#include <iostream>
template<typename T>
void printR (T const& arg) {
// …
}
int main() {
int arr1[5];
int arr3[5];
// printR(arr1);
return 0;
}
/* First instantiated from: insights.cpp:11 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
void printR<int[5]>(const int (&arg)[5])
{
}
#endif
上述如果给printR注释掉,那么编译期就不会生成对应的模板类型的代码。
而且上述arr1 ,arr3 都是int[5], 所以只会生成一个。
如果arr3[6], 就会生成两个了。
2.
template<typename T>
void printR (T arg) {
// …
}
如果上述模板改为这个样子,就会解析为int*
/* First instantiated from: insights.cpp:11 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
void printR<int *>(int * arg)
{
}
#endif
这个就是按值传递会导致类型退化(decay)
注意: 加入按值传递的模板后,需要把按const引用传递给删去,否则会出现调用时的ambiguous。当然如果不实例化的话就不会报错。
模板按非const引用传递
模板按非 const 引用传递可以避免类型退化,但是需要注意以下几点:
-
非 const 引用传递可能会修改传递的参数,因此在使用时需要慎重考虑是否需要修改参数。
-
非 const 引用传递需要传递一个左值,因此不能传递一个右值,这可能会限制函数的使用场景。
-
对于 const 对象,不能使用非 const 引用传递。因为 const 对象不能被修改,而非 const 引用传递的本质是将对象的地址传递给函数,如果函数尝试修改 const 对象会导致编译错误。
4.
到目前为止, 我们看到了将字符串常量和裸数组用作模板参数时的不同效果:
按值传递时参数类型会 decay, 参数类型会退化成指向其元素类型的指针。
按引用传递是参数类型不会 decay, 参数类型是指向数组的引用。
两种情况各有其优缺点。 将数组退化成指针, 就不能区分它是指向对象的指针还是一个被传递进来的数组。 另一方面, 如果传递进来的是字符串常量, 那么类型不退化的话就会带来问题, 因为不同长度的字符串的类型是不同的。