Подтвердить что ты не робот

Является ли decltype (auto) для структурированного привязки, который должен быть ссылкой?

Рассмотрим пример:

#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;
}

clang (вывод: false) и gcc (вывод: true) не согласуются в этом простом случае. Имея в виду, например, этот Q & As должен ли e быть ссылкой или это ошибка gcc? Или, может быть, код плохо сформирован?

4b9b3361

Ответ 1

Идентификаторы сами по себе являются ссылками. Из [dcl.struct.bind]/3:

Учитывая тип T i, обозначенный std​::​tuple_­element<i, E>​::​type, каждый v i является переменной типа "ссылка на T i", инициализированной с инициализатором, где ссылка является ссылкой lvalue, если инициализатор является значением lvalue и ссылкой rvalue иначе; ссылочный тип T i.

То есть, 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:

if e - это unparenthesized id-expression, называющее структурированное связывание ([dcl.struct.bind]), decltype(e) является ссылочным типом, как указано в спецификации структурированной привязки декларация;

Тип ссылки a равен int, поэтому e должен быть int. Это означает, что это не ссылка, а clang - правильная. Подано 81176.