我正在阅读Scott Meyers的有效现代C ++。第1项包含以下示例:
template<typename T>
void f(T& param); // param is a reference
int x = 27; // x is an int
const int cx = x; // cx is a const int
f(cx); // T is const int,
// param's type is const int&
在第3项中出现以下示例:
Widget w;
const Widget& cw = w;
auto myWidget1 = cw; // auto type deduction:
// myWidget1's type is Widget
根据第1项,我预计myWidget1
的类型为const Widget
。我错过了什么吗?
答案 0 :(得分:3)
在大多数情况下,auto
遵循模板参数推导的规则:
§7.1.6.4[dcl.spec.auto] / p6:
根据8.3确定 declarator-id 的类型后,声明的变量的类型 使用 declarator-id 是使用模板参数规则从其初始化程序的类型确定的 扣除。设
T
为已为变量标识符d
确定的类型。从P
获取T
使用新发明的类型模板参数auto
替换U
的出现次数,或者,如果初始化程序 是 braced-init-list (8.5.4),std::initializer_list<U>
。根据函数调用(14.8.2.1)中使用模板参数推导的规则确定推导出的变量d
的类型{/ 1}}。
§14.8.2.1[temp.deduct.call] / p2:
如果
A
不是参考类型:
[...]
如果
P
是cv限定类型,则类型扣除会忽略A
类型的顶级cv限定符。
如果您希望A
属于myWidget1
类型,则应将其声明为引用类型,例如:
const Widget&
答案 1 :(得分:1)
auto myWidget1 = cw;
遵循Meyers书中模板参数类型推导的第三条规则,即按值传递。
当你按值传递时,cv-qualifiers和references会被忽略,因为你得到了一个对象的新副本,所以你并不关心你复制的旧对象是const还是引用。