写const auto& [a, b] = f();
是否保证延长从f()
返回的对象的生命周期,或者至少绑定对象a
和b
?阅读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;意图,我想确定语言保证这是安全的。
答案 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
的返回值的生命周期。