结构化绑定:当某物看起来像引用并且行为类似于引用,但它不是引用时

structured bindings: when something looks like a reference and behaves similarly to a reference, but it's not a reference

昨天我在 SO 上看到 关于结构化绑定的内容。
我们可以总结如下。考虑下面的示例代码:

#include <tuple>
#include <type_traits>

int main() {
    auto tup = std::make_tuple(1, 2);
    auto & [ a, b ] = tup;
    // the following line won't compile for a isn't a reference
    // static_assert(std::is_reference_v<decltype(a)>);
}

在这种情况下 decltype(a)int(可能)因为 this bullet(工作草案):

if e is an unparenthesized id-expression naming a structured binding [...], decltype(e) is the referenced type as given in the specification of the structured binding declaration

Here 是@Curious 在评论中为感兴趣的人提供的 wandbox 片段。它表明实际上 a 不是引用,仅此而已。
到目前为止,对于原始问题来说还不错,OP 问为什么它是 int 而不是 int & 标准说 看起来是一个可以接受的答案。

不管怎样,我想知道委员会为什么这样决定。归根结底,a 指的是元组中的一个元素,我可以通过 a 修改该元素。换句话说,a 的声明看起来像一个引用,它的行为类似于引用,但它不是引用。

我可以接受这个,但我想知道这背后的原因是什么。为什么 decltype(a) 不能简单地 int &?是否有一个亵渎者可以理解的有意义的理由?

I wrote this yesterday:

decltype(x), where x is a structured binding, names the referenced type of that structured binding. In the tuple-like case, this is the type returned by std::tuple_element, which may not be a reference even though the structured binding itself is in fact always a reference in this case. This effectively emulates the behavior of binding to a struct whose non-static data members have the types returned by tuple_element, with the referenceness of the binding itself being a mere implementation detail.

之前已经讨论过这个主题(查看结构化绑定标记),您正在谈论的行为甚至在第二个答案中得到了解决。但是,p0144r2 第 3.5 节中阐明了基本原理:

Should the syntax be extended to allow const/&-qualifying individual names' types?

For example:

auto [&x, const y, const& z] = f(); // NOT proposed

We think the answer should be no. This is a simple feature to store a value and bind names to its components, not to declare multiple variables. Allowing such qualification would be feature creep, extending the feature to be something different, namely a way to declare multiple variables.

If we do want to declare multiple variables, we already have a way to spell it:

 auto val    = f();
 T& x        = get<0>(val);
 T2 const y  = get<1>(val);
 T3 const& z = get<2>(val);