非 const 何时按值捕获引用?

HCS*_*CSF 20 c++ g++ c++17

我正在查看 n4713 C++ 标准中的 8.4.4.1:

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&
};
}
Run Code Online (Sandbox Code Playgroud)

标准说 r2 有 type float const&,然后我尝试打印出类型:

#include <iostream>

template <class T>
void print_type() {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}

int main () {
    float x, &r = x;
    [=] {
        print_type<decltype(x)>();
        print_type<decltype((x))>();
        print_type<decltype(r)>();
        print_type<decltype((r))>();
    }();
}
Run Code Online (Sandbox Code Playgroud)

它给了:

void print_type() [with T = float]
void print_type() [with T = const float&]
void print_type() [with T = float&]
void print_type() [with T = float&]
Run Code Online (Sandbox Code Playgroud)

r2 的类型是float&而不是float const&。我做错什么了吗?

我用 g++ 8.3.1 编译。我也试过 9.1.0 但同样的事情。

Fed*_*dor 1

正如问题已经提到的, 的类型decltype((r))必须float const&符合标准,因为我们处于不可变的 lambda 中。

GCC 在您的示例中错误地打印了 type decltype((r))。Clang 和 Visual Studio 正确处理您的示例。

即使 GCC 仅在类型打印方面存在问题,它也不允许用户更改 引用的值r或初始化float &引用r

int main () {
    float x = 0, &r = x;
    [=]() {
        [[maybe_unused]] decltype((r)) q = r;
    }();
}
Run Code Online (Sandbox Code Playgroud)

https://gcc.godbolt.org/z/9oKzoeaq9