верхнего уровня и ссылки, но несколько отличается от того, как работает спецификатор >auto
. Когда выражение, к которому применен спецификатор >decltype
, является переменной, он возвращает тип этой переменной, включая спецификатор >const
верхнего уровня и ссылки.
>const int ci = 0, &cj = ci;
>decltype(ci) x = 0; // x имеет тип const int
>decltype(cj) y = x; // y имеет тип const int& и связана с x
>decltype(сj) z; // ошибка: z - ссылка, она должна быть инициализирована
Поскольку >cj
— ссылка, >decltype (cj)
— ссылочный тип. Как и любую другую ссылку, ссылку >z
следует инициализировать.
Следует заметить, что спецификатор >decltype
— единственный контекст, в котором переменная определена, поскольку ссылка не рассматривается как синоним объекта, на который она ссылается.
>decltype
и ссылкиКогда спецификатор >decltype
применяется к выражению, которое не является переменной, получаемый тип соответствует типу выражения. Как будет продемонстрировано в разделе 4.1.1, некоторые выражения заставят спецификатор >decltype
возвращать ссылочный тип. По правде говоря, спецификатор >decltype
возвращает ссылочный тип для выражений, результатом которых являются объекты, способные стоять слева от оператора присвоения.
>// decltype выражение может быть ссылочным типом
>int i = 42, *p = &i, &r = i;
>decltype(r + 0) b; // ok: сложение возвращает тип int; b имеет тип int
> // (не инициализирована)
>decltype(*p) с; // ошибка: с имеет тип int& и требует инициализации
Здесь >r
— ссылка, поэтому >decltype(r)
возвращает ссылочный тип. Если необходим тип, на который ссылается ссылка >r
, можно использовать ее в таком выражении, как >r + 0
, поскольку оно возвращает значение не ссылочного типа.
С другой стороны, оператор обращения к значению — пример выражения, для которого спецификатор >decltype
возвращает ссылку. Как уже упоминалось, при обращении к значению указателя возвращается объект, на который он указывает. Кроме того, этому объекту можно присвоить значение. Таким образом, >decltype(*p)
выведет тип >int&
, а не просто >int
.
>decltype
и >auto
в том, что выведение, осуществляемое спецификатором >decltype
, зависит от формы данного выражения. Не всегда понимают то, что включение имени переменной в круглые скобки влияет на тип, возвращаемый спецификатором >decltype
. При применении спецификатора >decltype
к переменной без круглых скобок получается тип этой переменной. Если заключить имя переменной в одни или несколько круглых скобок, то компилятор будет рассматривать операнд как выражение. Переменная — это выражение, которое способно быть левым операндом присвоения. В результате спецификатор >decltype
для такого выражения возвратит ссылку.>// decltype переменной в скобках - всегда ссылка
>decltype((i)) d; // ошибка: d - int& и должна инициализироваться
>decltype(i) e; // ok: e имеет тип int (не инициализирована)
>decltype((переменная))
(обратите внимание на парные круглые скобки) всегда возвращает ссылочный тип, а спецификатор