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

Делает запись 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. уродливее реализация всех наворотов для моего собственного типа, похоже, продлевает время жизни внешнего объекта и других его элементов данных.

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

27

Решение

Да. Хитрость заключается в том, чтобы понять, что, несмотря на внешний вид, часть объявления структурированной привязки перед [ не относится к именам в идентификатор-лист. Вместо этого они применяются к переменной, неявно введенной объявлением. [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возвращаемое значение.

18

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]