Рассмотрим случай:
std::tuple<int, int&>& foo();
auto& [x, y] = foo();
Что такое decltype(x)
и что такое decltype(y)
? Цель языковой функции заключается в том, чтобы x
было просто другим именем для foo().__0
, а y
- другим именем для foo().__1
, что означает, что они должны быть int
и int&
соответственно. Как указано сегодня, это распаковывается в & dagger; :
auto& __e = foo();
std::tuple_element_t<0, decltype(__e)>& x = std::get<0>(__e);
std::tuple_element_t<1, decltype(__e)>& y = std::get<1>(__e);
А правила работают так, что decltype(x)
- это тип, к которому x
относится , то есть int
. И decltype(y)
- это тип, к которому y
относится , поэтому int&
.
Если мы избежали tuple_element
, сделав что-то вроде:
auto&& x = std::get<0>(__e);
auto&& y = std::get<1>(__e);
Тогда мы не могли бы провести различие между x
и y
, потому что нет никакого способа разграничить то, что делают std::get<0>(__e)
и std::get<1>(__e)
: оба возвращают int&
.
Это также способ добавить согласованность между приведенным выше регистром и нормальным структурным регистром:
struct C {
int i;
int& r;
};
C& bar();
auto& [a, b] = bar();
Мы хотим, чтобы в целях структурированных привязок a
и b
здесь вели себя так же, как x
и y
здесь. И a
и b
здесь не введенные переменные, это просто разные имена для __e.i
и __e.r
.
<ч />
В нереферентном случае существует другой сценарий, в котором мы не можем различить:
std::tuple<int, int&&> foo();
auto [x, y] = foo();
Здесь мы сейчас распаковываем через:
auto __e = foo();
std::tuple_element_t<0, decltype(e)>& x = std::get<0>(std::move(__e));
std::tuple_element_t<1, decltype(e)>& y = std::get<1>(std::move(__e));
Оба std::get
вызова возвращают int&&
, поэтому вы не можете различить их, используя auto&&
... но результаты tuple_element_t
различны - int
и int&&
, соответственно. Эту разницу можно было бы увидеть и в обычном случае структуры.
<ч />
& dagger; Обратите внимание, что из-за CWG 2313 фактически распаковка происходит в ссылку на переменную с уникальным именем, а идентификаторы, указанные в привязке, просто ссылаются на эти объекты.