结构化绑定中的const引用是否延长了分解对象的生命周期?

时间:2016-12-16 02:06:21

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

const auto& [a, b] = f();是否保证延长从f()返回的对象的生命周期,或者至少绑定对象ab?阅读the proposal我不会在语言中看到任何明显的东西,以确保它确实存在,除非它被其他东西覆盖。但是,以下内容并没有延长临时的生命周期,因此我不知道如何覆盖它:

const auto& a = std::get<0>(f());

在论文的顶部,似乎表明它已被覆盖

  

分解声明的cv-qualifiers和ref-qualifier应用于为初始化程序引入的引用,而不是单个成员别名

但是在实际标准的拟议措辞中,我看到的最接近的提法如下,但我不确定如何阅读它以获得我正在寻找的保证:

  

如果e是未标记的id-expression,命名左值或引用   从分解声明的标识符列表中引入,   decltype(e)是在规范中给出的引用类型   分解声明

似乎gcc和clang都会根据wandbox experiment延长返回对象的生命周期,直到范围结束。实现我自己类型的所有花里胡哨的uglier one似乎延长了外部对象及其他数据成员的生命周期。

虽然几乎可以肯定作者和#39;意图,我想确定语言保证这是安全的。

1 个答案:

答案 0 :(得分:18)

是。诀窍是要意识到,尽管外观,[之前的结构化绑定声明的部分不适用于 identifier-list 中的名称。它们适用于声明隐式引入的变量。 [dcl.struct.bind]/1

  

首先,引入具有唯一名称e的变量。如果   初始化程序中的 assignment-expression 具有数组类型A,并且不存在 ref-qualifier e具有类型cv A并且每个元素都是从相应的元素进行复制初始化或直接初始化   由赋值表达式的形式指定的   初始化。否则,e被定义为 - 如果

     

attribute-specifier-seq opt decl-specifier-seq ref-qualifier opt < / sub> e 初始值设定项;

     

其中声明永远不会被解释为函数声明   除 declarator-id 之外的声明部分是   取自相应的结构化绑定声明。

然后将名称定义为e元素的别名或绑定到get上调用e结果的引用。

在您的示例中,它好像是(假设f返回两个元素std::tuple):

const auto& e = f(); // 1
using E = remove_reference_t<decltype((e))>;
std::tuple_element<0, E>::type& a = get<0>(e);
std::tuple_element<1, E>::type& b = get<1>(e);

(除了decltype(a)decltype(b)获得特殊处理以隐藏其参考性。)

很明显第1行确实延长了f的返回值的生命周期。