Выбрать главу

С другой стороны, оператор обращения к значению — пример выражения, для которого спецификатор decltype возвращает ссылку. Как уже упоминалось, при обращении к значению указателя возвращается объект, на который он указывает. Кроме того, этому объекту можно присвоить значение. Таким образом, decltype(*p) выведет тип int&, а не просто int.

Еще одно важное различие между спецификаторами decltype и auto в том, что выведение, осуществляемое спецификатором decltype, зависит от формы данного выражения. Не всегда понимают то, что включение имени переменной в круглые скобки влияет на тип, возвращаемый спецификатором decltype. При применении спецификатора decltype к переменной без круглых скобок получается тип этой переменной. Если заключить имя переменной в одни или несколько круглых скобок, то компилятор будет рассматривать операнд как выражение. Переменная — это выражение, которое способно быть левым операндом присвоения. В результате спецификатор decltype для такого выражения возвратит ссылку.

// decltype переменной в скобках - всегда ссылка

decltype((i)) d; // ошибка: d - int& и должна инициализироваться

decltype(i) e;   // ok: e имеет тип int (не инициализирована)

Помните, что спецификатор decltype((переменная)) (обратите внимание на парные круглые скобки) всегда возвращает ссылочный тип, а спецификатор decltype(переменная) возвращает ссылочный тип, только если переменная является ссылкой.

Упражнения раздела 2.5.3

Упражнение 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 выведут тот же тип, и пример, где они выведут разные типы.

2.6. Определение собственных структур данных

На самом простом уровне структура данных (data structure) — это способ группировки взаимосвязанных данных и стратегии их использования. Например, класс Sales_item группирует ISBN книги, количество проданных экземпляров и выручку от этой продажи. Он предоставляет также набор операций, таких как функция isbn() и операторы >>, <<, + и +=.

В языке С++ мы создаем собственные типы данных, определяя класс. Такие библиотечные типы, как string, istream и ostream, определены как классы, подобно типу Sales_item в главе 1. Поддержка классов в языке С++ весьма обширна, фактически части III и IV в значительной степени посвящены описанию средств, связанных с классами. Хотя класс Sales_item довольно прост, мы не сможем определить его полностью, пока не узнаем в главе 14, как писать собственные операторы.

2.6.1 Определение типа Sales_data

Несмотря на то что мы еще не можем написать свой класс Sales_item полностью, уже вполне можно создать достаточно реалистичный класс, группирующий необходимые элементы данных. Стратегия использования этого класса заключается в том, что пользователи будут получать доступ непосредственно к элементам данных и смогут самостоятельно реализовать необходимые операции.

Поскольку создаваемая структура данных не поддерживает операций, назовем новую версию Sales_data, чтобы отличать ее от типа Sales_item. Определим класс следующим образом:

struct Sales_data {

 std::string bookNo;