Тип привязки ссылки из std::tuple
Какой тип a
Вот?
#include <iostream>
#include <tuple>
using namespace std;
int main()
{
float x{};
std::tuple<int> tpl( x );
auto& [ a ] = tpl;
static_assert( std::is_same_v< decltype( a ), int> );
//static_assert( std::is_same_v< decltype( a ), int&> );
}
Согласно Стандарту 11.5 / 3:
[...] Учитывая тип Ti, обозначенный
std::tuple_element<i, E>::type
переменные вводятся с уникальными именами ri типа "ссылка на Ti", инициализированными инициализатором (11.6.3), где ссылка является ссылкой lvalue, если инициализатор является lvalue, и ссылкой rvalue в противном случае. Каждый vi - это имя l-типа типа Ti, которое относится к объекту, связанному с ri; ссылочный тип - Ti.
Вот, i
0 для первого элемента (int) и E
является std::tuple<int>
, так Ti
имеет тип std::tuple_element<0, std::tuple<int>>::type
т.е. int
, В дальнейшем ri
(a
в нашем случае) имеет тип "ссылка на Ti", т.е. int&
, но не только int
, Что не так в этой цитате и почему int
тип выводится как компиляторами clang, так и gcc?
2 ответа
Это правда, что тип переменной r0
является int&
, Но v0
здесь называется a
, это другая вещь, имя структурированной привязки, и технически вообще не является переменной, просто это другой тип имени.
Итак, нам нужно посмотреть на описание decltype
в [dcl.type.decltype]:
Для выражения
e
тип обозначенdecltype(e)
определяется следующим образом:
- если
e
это не заключенное в скобки id-выражение, обозначающее структурированную привязку,decltype(e)
ссылочный тип, указанный в спецификации объявления структурированной привязки;
Так что здесь "ссылочный тип" просто int
,
Конечно, decltype((a))
является int&
как и следовало ожидать. decltype
имя без двойных скобок используется для определения того, как имя "объявлено", а не как оно ведет себя, поэтому не очевидно, что decltype(a)
"должен" быть одно или другое, так как a
не имеет нормального объявления. Хотя это потенциально немного полезно, учитывая std::tuple<int, int&> t{0, n}; auto& [a, b] = t;
, у нас есть decltype(a)
является int
но decltype(b)
является int&
,
Заметка
ссылочный тип - Ti.
Для структурированных привязок, decltype
возвращает ссылочный тип ( [dcl.type.decltype]):
если
e
это не заключенное в скобки id-выражение, обозначающее структурированную привязку,decltype(e)
ссылочный тип, указанный в спецификации объявления структурированной привязки;