decltype для переменной ссылочного типа с фигурными скобками
Рассмотрим следующий код :
#include <type_traits>
int main() {
const int& p = 42;
auto v1 = decltype(p){};
static_assert(std::is_same_v<decltype(v1), int>);
decltype(p) v2{};
static_assert(std::is_same_v<decltype(v2), const int&>);
// auto v3 = X(const int&)X {};
}
Тип v1
выводится как int
. При этом v2
ожидаемо выводится тип const int&
. Я думаю, что первый шаг v1
можно рассматривать как добавление еще одного псевдонима типа, using T = decltype(p);
а затем auto v4 = T{};
. Как это выражение ( decltype(p){}
или T{}
) трактуется компилятором? Я знаю, что эта {}
часть предназначена для создания экземпляра, но почему результирующий тип v1
не является ссылочным типом?
Еще один вопрос: есть ли способ объявить v3
переменную того же типа, что и v1
явно указанный тип const int&
(вместо decltype(p)
)?
Приветствуются любые ссылки на стандарт.
Ответы
(Тем, кто проголосовал против: если вы проголосовали против, потому что считаете, что цитирование Скотта Мейерса не эквивалентно цитированию стандарта, да ладно ...)
Как вы можете прочесть из « Эффективного современного C ++» (дополненного той частью исправлений, которую вы можете найти, Case 2:
выполнив поиск по этой ссылке, и это просто упрощает чтение следующего текста, но это не существенно для вопроса):
Если
ParamType
это не ссылка [...], еслиexpr
тип является ссылкой, игнорируйте ссылочную часть. Если [...]expr
естьconst
, примите это тоже. Если это такvolatile
, также игнорируйте это.
где param
- спецификатор объявления, который в вашем случае является справедливым auto
, т.е. не является ссылкой.
Другими словами, вы создаете с v1
помощью простого auto
(не auto&
), то есть путем копирования, поэтому не имеет значения, инициализируете ли вы его с помощью сущности, которая является ссылкой или нет, или даже с помощью const
или нет ( volatile
или нет, fwiw), потому что вы его копируете.
Подумайте о более простом случае,
int i = 3;
int& p = i;
auto v1 = p;
насколько это v1
касается, это действительно не важно , является ли он initalized с одной ( i
) или другой ( p
) имя , под которым же известно лицо, потому что он получит копию того , что значение , которое компания имеет.
auto
вывод типа работает так же, как вывод типа шаблона (за исключением разницы в том, как они работают с инициализатором в фигурных скобках, что в данном случае не имеет значения), и для обоих из них вы можете обратиться к Эффективному современному C ++ Скотта Мейерса .