template<typename T>
void fun(T& param) // param is a reference
{
T abc;
abc=1;//cannot change abc value because T is deduced as const int
//It gives compilation error because T is deduced as const int
}
template<typename T>
void fun1(const T& param) // param is a reference
{
T abc;
abc=1;//can change abc value because T is deduced as int
//why T is deduced int here
}
int main()
{
int x = 2; // x is an int
const int cx = x; // cx is a const int
const int& rx = x; // rx is a reference to x as a const int
fun(x); // T is int, param's type is int&
fun(cx); // T is const int, param's type is const int&
fun(rx); // T is const int,param's type is const int&
fun1(x); // T is int, param's type is int&
fun1(cx); // T is int, param's type is const int&
fun1(rx); // T is int,param's type is const int&
return 0;
}
更新
const int cx
和const int& rx
实例化但是const int(T)类型是为了娱乐而推导出来的(函数模板)?答案 0 :(得分:3)
当你有像
这样的模板功能时template<typename T>
void fun(T & param)
如果传递的参数实际上是const
或volatile
,那么在模板实例化中,T
也将适当地“cv-qualified”。
当你将cv-qualifier放在模板函数声明中时,就像这样,
template<typename T>
void fun(const T & param)
然后T
不绑定为const
。但如果参数volatile
。
volatile
它实际上非常直观 - T
是最简单的类型,它将使函数调用工作,即使函数参数的预期类型与传递的相匹配。
同样,如果我的功能是
template <typename T>
void fun(T * param)
然后,如果我将int *
传递给T
,则int
将被绑定为[temp.deduct.call](14.8.2.1)
。
这在C ++ 11标准Uint8Array
中有详细描述,请参阅第三部分关于CV限定符的内容:
[temp.deduct.call](14.8.2.1)
(1)模板参数推导是通过比较每个函数模板参数类型(称之为P)来完成的 调用的相应参数的类型(称之为A),如下所述。 ... (2)如果P不是参考类型:
(2.1) - 如果A是数组类型,则数组到指针标准转换(4.2)产生的指针类型是 代替A代替类型扣除;否则,
(2.2) - 如果A是函数类型,则函数到指针标准转换产生的指针类型(4.3) 用于代替A进行类型扣除;否则,
(2.3) - 如果A是cv限定类型,则类型扣除将忽略A类型的顶级cv限定符。
(3)如果P是cv限定类型,则类型推导忽略P类型的顶级cv限定符。如果P是a 引用类型,P引用的类型用于类型推导。
答案 1 :(得分:2)
由于此处cx
和rx
表现出相同的行为,我们仅使用cx
。
cx
是const int
。
fun
的情况: T&
与const int
匹配,因此T
被推断为const int
,因为const
不属于T &
。 param
的类型为const int&
。
fun1
的情况: const T&
与const int
匹配,因此T
被推断为int
,因为const
已经在const T&
中。 param
的类型为const int&
。
让我们通过类型匹配在视觉上水平对齐,也许这更清楚:
fun param type: | T | &
receives : | const int |
fun1 param type: | const | T | &
receives : | const | int |