为何decltype((const int)a)与decltype((const int)1)的类型不同?
解答
这是个很典型的C类型推导细节问题,核心在于C标准对非类类型纯右值的cv限定符处理规则,再加上g++ 7.3的具体实现特性,我来一步步拆解:
1. 先理清两个核心概念
- 左值(lvalue):代表占据内存空间的实体(比如变量
a),可以被取地址。 - 纯右值(prvalue):临时值或字面量,不占用持久内存,无法被取地址(比如数字
1,或者转换生成的临时值)。
C++标准有一条关键规则:对于非类、非数组类型的纯右值,其const/volatile限定符会被自动忽略。因为纯右值本身不可修改,这些限定符对这类表达式没有实际意义,编译器会在类型分析阶段剔除它们。
2. 分析decltype((const int)a)
a是int类型的左值,(const int)a是显式转换表达式:它会把左值a转换为const int类型的纯右值。- 根据上面的规则,这个
const int类型的纯右值会被编译器调整为int类型(去掉const限定)。 - 所以
decltype((const int)a)最终推导出来的类型是int,对应报错中的td<int> t1。
3. 分析decltype((const int)1)
1本身是int类型的字面量纯右值,(const int)1是将这个字面量转换为const int类型的纯右值。- 在g++ 7.3的实现中,对于字面量转换得到的
const int纯右值,编译器没有应用cv限定符的忽略规则,而是保留了const int类型。这是因为字面量本身就具备不可修改的特性,编译器认为这里的const限定符是有意义的,所以没有剔除它。 - 因此
decltype((const int)1)推导出来的类型是const int,对应报错中的td<const int> t2。
总结
两者的差异本质上是:左值转换生成的非类类型纯右值会被去掉cv限定,而字面量转换生成的同类型纯右值在g++ 7.3中保留了cv限定。这是C++标准规则与编译器具体实现细节共同作用的结果。
内容的提问来源于stack exchange,提问作者olist
相关产品推荐
相关产品推荐

