Подтвердить что ты не робот

Сопоставляют ли ссылки const в структурированных привязках время жизни разложенного объекта?

Обеспечивает ли запись const auto& [a, b] = f(); продление срока службы объекта, возвращаемого из f(), или, по крайней мере, связаны объекты a и b? Прочитав предложение, я не вижу ничего очевидного на этом языке, чтобы убедить меня, что это произойдет, если только оно не будет покрыто чем-то другим. Тем не менее, следующее не продлевает время жизни временного, поэтому я не вижу, как он будет покрыт:

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

В верхней части статьи, похоже, предполагается, что она покрыта

cv-квалификаторы и ref-квалификатор объявления декомпозиции применяются к ссылке, введенной для инициализатора, а не для отдельных псевдонимов элементов

Но в предложенной формулировке для фактического стандарта самое близкое упоминание, которое я вижу ниже, хотя я не уверен, как его прочитать, чтобы получить гарантию, которую я ищу:

если e - несферированное id-выражение, обозначающее lvalue или reference введенный из идентификатора-списка объявления декомпозиции, decltype (e) является ссылочным типом, указанным в спецификации объявление разложения

Кажется, что gcc и clang продлевают время жизни объекта, возвращаемого до конца области, основываясь на эксперименте wandbox . уродливый, реализующий все колокола и свистки для моего собственного типа, как представляется, увеличивает время жизни внешнего объекта и других его членов.

Хотя почти наверняка намерения авторов, я хотел бы точно знать, что язык гарантирует, что это безопасно.

4b9b3361

Ответ 1

Да. Трюк заключается в том, чтобы понять, что, несмотря на внешний вид, часть объявления структурированного связывания перед [ не применяется к именам в списке идентификаторов. Вместо этого они применяются к переменной, введенной неявно декларацией. [dcl.struct.bind]/1:

Сначала вводится переменная с уникальным именем e. Если выражение-присваивание в инициализаторе имеет тип массива A и не содержит ref-qualifier, e имеет тип cv A, и каждый элемент инициализируется или прямо инициализируется из соответствующего элемента выражения-присваивания, указанного в форме инициализатор. В противном случае e определяется как-if через

атрибут-specifier-seq opt decl-specifier-seq ref-qualifier opte initializer;

где объявление никогда не интерпретируется как объявление функции и части декларации, отличные от идентификатора декларатора, взятых из соответствующей декларации структурированного связывания.

Затем имена определяются как псевдонимы для элементов e или ссылок, связанных с результатом вызова get на e.

В вашем примере это как будто by (при условии, что 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.