为什么 "const auto [x, y]" 在绑定到引用类型时没有按预期运行?

Why does "const auto [x, y]" not behave as expected when binding to reference types?

以下代码片段摘自cppref

std::tuple<int, int&> f();

auto [x, y] = f(); 
// decltype(x) is int
// decltype(y) is int&

const auto [z, w] = f();
// decltype(z) is const int
// decltype(w) is int&

我的问题在最后一行:

为什么decltype(w)int&而不是const int&?

这将是引用本身,而不是常量的引用值。由于引用无论如何都不可修改,所以没有常量引用这样的东西。

Jarod42 回答了评论中的问题,让我在这里引用标准的相关部分,来自 [dcl.struct.bind]¹:

Given the type Ti designated by std​::​tuple_­element​::​type, variables are introduced with unique names ri of type “reference to Ti” initialized with the initializer ([dcl.init.ref]), where the reference is an lvalue reference if the initializer is an lvalue and an rvalue reference otherwise. Each vi is the name of an lvalue of type Ti that refers to the object bound to ri; the referenced type is Ti.

因此在 const auto [z, w] = f(); 中,您有 const T1T1intconst T2T2int& .由于 const 修改了其左侧的内容,因此变为 int& const 并导致 int&.

请注意,int& const 变为 int& 仅在模板参数替换中才有可能,即,这不会编译:

int n = 42;
int& const doesntWork = n; // Error: 'const' qualifiers cannot be applied to 'int&'

但这确实:

template <class T> void f(const T t)
{
   ++t;
}

int n = 42;

f<int&>(n);

其中发生与上述相同的从 int& constint& 的收缩。

¹ 感谢@cpplearner 将我指向此处的确切段落。