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

时间:2017-06-22 09:39:10

标签: c++ language-lawyer c++17 structured-bindings

昨天我在这里看到an interesting question关于结构化绑定的问题 我们可以总结如下。请考虑以下示例代码:

#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)>);
}

在这种情况下,由于this bullet(工作草案),decltype(a)(可能)int

  

如果e是一个未加括号的id-expression,命名一个结构化绑定[...],decltype(e)是结构化绑定声明规范中给出的引用类型

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

无论如何,我想知道委员会为何如此决定。在一天结束时,a引用元组中的元素,我可以通过a修改该元素。换句话说,a的声明看起来像是一个引用,它的行为类似于引用,但它不是引用。

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

2 个答案:

答案 0 :(得分:10)

I wrote this yesterday

  

decltype(x),其中x是结构化绑定,为引用命名   结构化绑定的类型。在类似元组的情况下,这就是   std::tuple_element返回的类型,可能不是引用   即使结构化绑定本身实际上总是如此   在这种情况下参考。这有效地模仿了行为   绑定到非静态数据成员具有类型的结构   由tuple_element返回,具有绑定的参考性   本身只是一个实施细节。

答案 1 :(得分:-1)

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

中详细说明
  

是否应将语法扩展为允许 public static IEnumerable<IEnumerable<T>> SubSetsOf<T>(IEnumerable<T> source) { if (!source.Any()) return Enumerable.Repeat(Enumerable.Empty<T>(), 1); var element = source.Take(1); var haveNots = SubSetsOf(source.Skip(1)); var haves = haveNots.Select(set => element.Concat(set)); return haves.Concat(haveNots); } private static bool Valid(IEnumerable<int> set) { bool flag = false; foreach (var element in set) { var f = element > 0; if (f == flag) { return false; } flag = f; } return true; } - 符合条件的个人   名称&#39;类型?

     

例如:

const/&
     

我们认为答案应该是否定的。这是一个存储的简单功能   value并将名称绑定到其组件,而不是声明多个   变量。允许这样的资格将是特征蠕变,   将功能扩展为不同的东西,即一种方式   声明多个变量。

     

如果我们确实要声明多个变量,我们已经有办法了   拼写:

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