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