×
Traktatov.net » Язык программирования C++. Пятое издание » Читать онлайн
Страница 60 из 714 Настройки

верхнего уровня и ссылки, но несколько отличается от того, как работает спецификатор >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((переменная)) (обратите внимание на парные круглые скобки) всегда возвращает ссылочный тип, а спецификатор