【问题标题】:Type of expression consisting only of a variable identifier仅由变量标识符组成的表达式类型
【发布时间】:2019-06-17 18:14:14
【问题描述】:

cppreference 说:

命名变量、函数、概念的特殊化(C++20 起)或枚举数的标识符可用作表达式。仅由标识符组成的表达式的结果是由标识符命名的实体。 [...] 表达式的类型确定如下:

[...] 否则,表达式的类型与命名实体的类型相同

这不是错误吗?如果实体是引用,例如:

int &a = ...

那么a作为实体的类型是int &,但是a作为表达式的类型只有int,不是吗?表达式的类型是never a reference:

[...] 每个表达式都有一些非引用类型

额外问题:a 的类型(作为表达式)是 int 还是 int & 有关系吗?如果是,它有什么不同?


注意:decltype 使用相同的措辞:

如果参数是不带括号的 id 表达式或不带括号的类成员访问表达式,则 decltype 产生 由该表达式命名的实体的类型

但很明显,decltype(a)int &

【问题讨论】:

    标签: c++ language-lawyer


    【解决方案1】:

    这是标准(草案)所说的:

    [expr.type] 表达式/类型

    如果一个表达式最初的类型是“对 T 的引用”,则在进一步分析之前将该类型调整为 T。 ...

    因此,很明显,一个表达式可以有一个引用类型——最初,在调整类型分析之前。

    “每个表达式都有一些非引用类型”是不是真的?

    取决于你如何解释它。一个表达式可以有一个非引用类型(最初),但所有表达式都有一些非引用类型(调整后)用于类型分析。

    [expr.prim.id.unqual] 表达式/非限定名称

    结果是标识符表示的实体。 ... 如果实体是 T 类型模板参数的模板参数对象 ... [不适用] ... 否则,表达式的类型是结果的类型。 [注:类型 如果它是 cv-qualified 或者是引用类型,将按照 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 命名的实体的类型。

    【讨论】:

    • 那么,在这种情况下,“每个表达式都有一些非引用类型”是不正确的?
    • @geza 取决于您如何解释它。表达式可以有非引用类型,但所有表达式都有一些非引用类型(调整后),可用于类型分析。
    • 所以,基本上,a 的类型(作为表达式)是int &,但是我们用它做什么(进一步分析?),它变成了int?为什么它的类型不是int?这有关系吗?例如,无论哪个为真,decltype(a)decltype((a)) 都将是int &
    • @geza 如果没有初始引用类型,那么您无法为表达式是左值还是 xvalue 制定规则(这可能取决于引用的类型 - 不是以防万一虽然是 id 表达式)。
    • 嗯。 int &&a = ...。这里,a 是一个右值引用,而a 是一个左值。所以我不确定这是不是这个原因。
    【解决方案2】:

    这不是错误吗?

    没有。 a 的类型是 int。是的,这只是在类型调整之前,但由于总是会发生,因此谈论具有引用类型的表达式是没有意义的,因为引用会立即消失。

    a 的类型(作为表达式)是 int 还是 int & 有关系吗?如果是,它有什么不同?

    这基本上是在问我们为什么需要价值类别。基本上它会破坏移动语义,因为右值引用有时是 xvalues,有时是 lvalues。

    【讨论】:

    • cppreference: "命名实体的类型。" vs你:“一个实体没有类型。”。有人说错了。 “a 的类型是 int”。你的意思是a 作为一个变量,还是a 作为一个表达式?你不是要写int &吗?这对我来说更有意义。
    • @geza 我的意思是表达。不错,实体可以是名称空间之类的东西,显然没有类型。你是对的
    猜你喜欢
    • 1970-01-01
    • 2016-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多