为什么 decltype(captured_var) 的行为不如预期?

Why does decltype(captured_var) not behave as expected?

#include <type_traits>

int x = 0;
void f(int const x)
{
    static_assert(std::is_const_v<decltype(x)>); // ok
}

int main() 
{
    int n = 0;
    [n, m = n]
    {
        static_assert(std::is_const_v<decltype(m)>); // ok
        static_assert(std::is_const_v<decltype(n)>); // err
    };
}

online demo

为什么 decltype(captured_var) 没有按预期运行?

注意在decltype(n)中,n指的是在main()中定义的局部变量n,而不是闭包类型的成员(如你所料) ).

[expr.prim.lambda.capture]/11

(强调我的)

Every id-expression within the compound-statement of a lambda-expression that is an odr-use of an entity captured by copy is transformed into an access to the corresponding unnamed data member of the closure type.

[Note 7: An id-expression that is not an odr-use refers to the original entity, never to a member of the closure type. However, such an id-expression can still cause the implicit capture of the entity. — end note]


顺便说一句:Gcc 似乎直接为非可变 lambda 声明了数据成员 const。这就是为什么 decltype(m) 得到 const int 的原因。按照标准,[expr.prim.lambda.capture]/10.2

(强调我的)

The type of such a data member is the referenced type if the entity is a reference to an object, an lvalue reference to the referenced function type if the entity is a reference to a function, or the type of the corresponding captured entity otherwise.

我认为gcc是错误的; decltype(m) 应该导致类型 int。无论如何,decltype(n) 确实引用了局部变量 n,您可以通过例如将 n 的类型更改为 int&&.

Gcc LIVE
Clang LIVE