Делает запись 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. уродливее реализация всех наворотов для моего собственного типа, похоже, продлевает время жизни внешнего объекта и других его элементов данных.
Хотя почти наверняка намерения автора (-ов), я хотел бы знать наверняка, что язык гарантирует, что это безопасно.
Да. Хитрость заключается в том, чтобы понять, что, несмотря на внешний вид, часть объявления структурированной привязки перед [
не относится к именам в идентификатор-лист. Вместо этого они применяются к переменной, неявно введенной объявлением. [Dcl.struct.bind] / 1:
Во-первых, переменная с уникальным именем
e
вводится. Если
Назначение выражение в инициализатор имеет тип массиваA
и нет реф-классификатор настоящее,e
имеет типcv A
и каждый элемент инициализируется копией или инициализируется напрямую из соответствующего элемента
из Назначение выражение как указано в форме
инициализатор. Иначе,e
определяется как-будтоАтрибут спецификатор-слвыбирать Децл-спецификатор-сл реф-классификаторвыбирать
e
инициализатор ;где объявление никогда не интерпретируется как объявление функции
и части декларации, кроме описатель-идентификатор являются
взяты из соответствующей декларации структурированного связывания.
Затем имена определяются как псевдонимы для элементов 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
возвращаемое значение.
Других решений пока нет …