Рассмотрим пример:
#include <iostream>
#include <type_traits>
#include <tuple>
int main() {
auto tup = std::make_tuple(1, 2);
auto [ a, b ] = tup;
decltype(auto) e = a;
std::cout << std::boolalpha << std::is_reference_v<decltype(e)> << std::endl;
}
лязг (выход: false
) а также НКУ (выход: true
) не согласны в этом простом случае. Имея в виду, например, этот вопрос&Как если e
быть ссылкой или это ошибка GCC? Или, может быть, код плохо сформирован?
Идентификаторы самих себя ссылки. От [Dcl.struct.bind] / 3:
Учитывая тип Тя обозначено
std::tuple_element<i, E>::type
каждый vя переменная типа «ссылка на Tя»Инициализируется инициализатором, где ссылка является ссылкой lvalue, если инициализатор является ссылкой lvalue, а в противном случае ссылка rvalue; ссылочный тип — Tя.
То есть, a
а также b
оба int&&
,
Но путь decltype(auto)
на самом деле ведет себя из [Dcl.type.auto.deduct]:
Если заполнитель является
decltype(auto)
тип спецификатор,T
должен быть только заполнителем. Тип выведенный дляT
определяется как описано в [dcl.type.simple], как будтоe
был операндомdecltype
,
Эта формулировка действительно неловкая, но в конечном итоге:
decltype(auto) e = a;
~~~~~~~~~~~~~~
средства:
decltype( a ) e = a;
~~~~
а также decltype(a)
значит, из [Dcl.type.simple] /4.1:
если
e
это без скобок ID-выражение именование структурированной привязки ([dcl.struct.bind]),decltype(e)
является ссылочный тип как указано в спецификации объявления структурированной привязки;
ссылочный тип из a
является int
, так e
должен быть int
, Это означает, что это не ссылка, и лязг — это правильно. Поданный 81176.
Других решений пока нет …