Kan*_*ane 46 c++ language-lawyer
鉴于此代码:
#include <iostream>
template<typename T>
void modify(const T &j){ j = 42; } // j has type int&
int main()
{
int i = 10;
modify<int&>(i); // T=int&
std::cout << i; // 42 is printed
}
Run Code Online (Sandbox Code Playgroud)
为什么会const T &j
变成int &j
if T=int&
?会发生什么const
?
eer*_*ika 33
没有引用引用这样的东西,即没有T & &
.
给定const T&
where T
is int&
,该类型会折叠为int&
.
const 会发生什么?
也没有 const 引用这样的东西,即没有T & const
(不要与对 const 的引用混淆,const 确实存在并且通常通俗地称为 const 引用)。不能修改引用(这与修改引用的对象不同),因此常量没有意义。const 在这里被简单地忽略了。
标准规则(来自最新草案):
[dcl.ref] 如果 typedef-name ([dcl.typedef], [temp.param]) 或 decltype-specifier ([dcl.type.simple]) 表示类型 TR 是对类型 T 的引用,尝试创建类型“对 cv TR 的左值引用”会创建类型“对 T 的左值引用”,而尝试创建类型“对 cv TR 的右值引用”会创建类型 TR。[ 注意:此规则称为参考折叠。— 尾注 ]
这里 cv 指的是 cv 限定符,即 const 和 volatile。
澄清为什么这适用于模板参数:
[temp.param] 标识符不跟随省略号的类型参数将其标识符定义为 typedef-name ...
PS 指定引用折叠的方式是完美转发工作的部分原因。
我总是建议人们采用East-const风格,总是将 放在const
它所符合的右边(东),而你只是遇到了一个让一切变得不同的情况。
使用 West-const 表示法,您已编写:
template<typename T>
void modify(const T &j){ j = 42; } // j has type int&
Run Code Online (Sandbox Code Playgroud)
代int&
的T
,你是天真地进行文本替换,就好像它是一个宏,思考的j
作为const int && j
。事实并非如此。
使用 East-const 表示法,你会写:
template<typename T>
void modify(T const& j){ j = 42; }
Run Code Online (Sandbox Code Playgroud)
替换int&
为T
,您会得到int& const& j
:注意const
根本不在您认为的位置?
而现在,这个世界又变得有意义了。你有一个引用的常量引用int
:
const
,所以你不能修改引用本身......但是你永远不能。int
不是const
,所以你可以修改int
。CQFD。
归档时间: |
|
查看次数: |
1599 次 |
最近记录: |