Гарантирует ли запись const auto& [a, b] = f(); продление срока службы объекта, возвращаемого из f(), или, по крайней мере, объекты, к которым привязаны a и b? Читая предложение, я не вижу ничего очевидного в язык, чтобы убедиться, что это так, если только он не покрыт чем-то другим. Однако следующее не продлевает срок службы временного объекта, поэтому я не понимаю, как это будет покрыто:
const auto& a = std::get<0>(f());
В верхней части бумаги кажется, что она покрыта
квалификаторы cv и ref объявления декомпозиции применяются к ссылке, введенной для инициализатора, а не для отдельных псевдонимов членов
Но в предложенной формулировке фактического стандарта самое близкое упоминание, которое я вижу, приведено ниже, хотя я не уверен, как его читать, чтобы получить гарантию, которую я ищу:
если e является выражением id без скобок, именующим lvalue или ссылку, введенную из списка идентификаторов объявления декомпозиции, decltype(e) является типом, на который указывает ссылка, как указано в спецификации объявления декомпозиции
Похоже, что gcc и clang продлевают время жизни возвращаемого объекта до конца области видимости на основе эксперимента с wandbox. более уродливый, реализующий все навороты для моего собственного типа, кажется, продлевает время жизни внешнего объекта и других его данных. члены.
Хотя почти наверняка намерения авторов, я хотел бы знать наверняка, что язык гарантирует, что это безопасно.
Ответ 1 · рейтинг 22 · T.C.
Да. Хитрость заключается в том, чтобы понять, что, несмотря на внешний вид, часть объявления структурированной привязки перед [ не применяется к именам в списке-идентификаторов. Вместо этого они применяются к переменной, неявно введенной объявлением. [dcl.struct.bind]/1:
Во-первых, вводится переменная с уникальным именем e. Если выражение-присваивания в инициализаторе имеет тип массива A и отсутствует квалификатор ссылки, e имеет тип cv A и каждый элемент копируется -инициализируется или инициализируется напрямую из соответствующего элемента выражения-присваивания, как указано в форме инициализатора. В противном случае e определяется как если бы
attribute-specifier-seqopt decl-specifier-seq ref-qualifieropt 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.