可以将命名变量,函数,概念的特殊性(自C ++ 20起)或枚举器的标识符用作表达式。仅由标识符组成的表达式的结果是由标识符命名的实体。 [...]表达式的类型确定如下:
[...] 否则,表达式的类型与名为的实体的类型相同。
这不是错误吗?如果实体是参考,例如:
int &a = ...
然后a
作为实体的类型为int &
,但是a
作为表达式的类型仅为int
,不是吗?表达式的类型为never a reference:
[...]每个表达式都有一些非引用类型
奖金问题:a
的类型(作为表达式)是int
还是int &
,这有关系吗?如果是,它在哪里有作用?
注意:decltype使用相同的措词:
如果参数是未括号化的id表达式或未括号化的类成员访问表达式,则decltype会产生该表达式命名的实体的类型。
但是很明显,decltype(a)
是int &
。
答案 0 :(得分:1)
这是标准(草稿)所说的:
[expr.type]表达式/类型
如果表达式最初的类型为“对T的引用”,则在进行任何进一步分析之前,将类型调整为T。 ...
因此,很明显,表达式可以具有引用类型-最初是在调整类型分析之前。
“每个表达式都有一些非引用类型”是不是?
取决于您的解释方式。表达式可以(最初)具有非引用类型,但是所有表达式都具有某种非引用类型(调整后),用于类型分析。
[expr.prim.id.unqual]表达式/不合格的名称
结果是由标识符表示的实体。 ...如果实体是类型T的模板参数的模板参数对象... [不适用] ...否则,表达式的类型就是结果的类型。 [注意:类型 如果它是cv合格或参考类型,则将按照7.2.2中的描述进行调整。 —尾注] ... [示例:
void f() { float x, &r = x; [=] { decltype(x) y1; // y1 has type float decltype((x)) y2 = y1; // y2 has type float const& because this lambda // is not mutable and x is an lvalue decltype(r) r1 = y1; // r1 has type float& decltype((r)) r2 = y2; // r2 has type float const& }; }
—结束示例]
Decltype说明符[dcl.type.decltype]
...如果e是未括号的id表达式或...,则decltype(e)是e命名的实体的类型。
答案 1 :(得分:0)
这不是错误吗?
不。 a
的类型为int
。是的,这只是在类型调整之前,但是由于总是发生,因此谈论具有引用类型的表达式是没有意义的,因为引用会立即消失。
这是否重要,
a
的类型(作为表达式)是int
还是int &
?如果是,它在哪里有作用?
这基本上是在问为什么我们根本需要值类别。基本上,由于右值引用有时是xvalues,有时是lvalues,它将破坏移动语义。