- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Язык программирования C++. Пятое издание - Стенли Липпман
Шрифт:
Интервал:
Закладка:
Подобно статическим членам обычного класса, к статическому члену шаблона класса можно обратиться через объект класса или непосредственно, при помощи оператора области видимости. Конечно, чтобы использовать статический член через класс, следует обратиться к его конкретному экземпляру:
Foo<int> fi; // создает экземпляр класса Foo<int>
// и статической переменной-члена ctr
auto ct = Foo<int>::count(); // создает экземпляр Foo<int>::count()
ct = fi.count(); // использует Foo<int>::count()
ct = Foo::count(); // ошибка: экземпляр какого именно
// шаблона создается?
Как и любая другая функция-член, экземпляр статической функции-члена создается только при его использовании в программе.
Упражнения раздела 16.1.2Упражнение 16.9. Что такое шаблон функции? Что такое шаблон класса?
Упражнение 16.10. Что происходит при создании экземпляра шаблона класса?
Упражнение 16.11. Следующее определение шаблона List неправильно. Как его исправить?
template <typename elemType> class ListItem;
template <typename elemType> class List {
public:
List<elemType>();
List<elemType>(const List<elemType> &);
List<elemType>& operator=(const List<elemType> &);
~List();
void insert(ListItem *ptr, elemType value);
private:
ListItem *front, *end;
};
Упражнение 16.12. Напишите собственные версии шаблонов Blob и BlobPtr, включая все константные члены, которые не были представлены в тексте.
Упражнение 16.13. Объясните, какой вид дружественных отношений вы выбрали бы для операторов равенства и сравнения шаблона BlobPtr.
Упражнение 16.14. Напишите шаблон класса Screen, который использует параметры значения для определения высоты и ширины экрана.
Упражнение 16.15. Реализуйте операторы ввода и вывода для своего шаблона Screen. Какие друзья необходимы классу Screen (если таковые вообще имеются) для работы операторов ввода и вывода? Объясните, зачем нужно каждое объявление дружественным (если таковые вообще имеются).
Упражнение 16.16. Перепишите класс StrVec (см. раздел 13.5), как шаблон Vec.
16.1.3. Параметры шаблона
Подобно именам параметров функций, имена параметров шаблона не имеют никакого значения. Обычно параметрам типа присваивают имя Т, но можно использовать любое другое:
template <typename Foo> Foo calc(const Foo& a, const Foo& b) {
Foo tmp = a; // тип tmp совпадает с типом параметров и возвращаемого
// значения
// ...
return tmp; // типы возвращаемого значения и параметров совпадают
}
Параметры шаблона и область видимостиПараметры шаблона следуют обычным правилам области видимости. Имя параметра шаблона применимо сразу после его объявления и до конца объявления или определения шаблона. Подобно любым другим именам, параметр шаблона скрывает любые объявления имен во внешней области видимости. Однако, в отличие от большинства других контекстов, имя, используемое как параметр шаблона, не может быть повторно использовано в пределах шаблона:
typedef double А;
template <typename A, typename В> void f(А а, В b) {
A tmp = а; // tmp имеет тип параметра шаблона А, а не double
double В; // ошибка: повторное объявление параметра шаблона В
}
Согласно обычным правилам сокрытия имен, определение typedef типа А скрывается определением параметра типа по имени А. Таким образом, переменная tmp не будет иметь тип double; она будет иметь любой тип, который будет передан параметру шаблона А при использовании шаблона. Поскольку нельзя многократно использовать имена параметров шаблона, объявление переменной по имени B ошибочно.
Поскольку имя параметра не может быть использовано многократно, в каждом списке параметров шаблона имя параметра шаблона может присутствовать только однажды:
// ошибка: повторение имени V в параметрах шаблона недопустимо
template <typename V, typename V> // ...
Объявления шаблонаОбъявление шаблона должно включить параметры шаблона:
// объявляет, но не определяет compare и Blob
template <typename Т> int compare(const T&, const T&);
template <typename T> class Blob;
Подобно параметрам функций, имена параметров шаблона не должны совпадать с таковыми в объявлениях и определениях того же шаблона:
// все три случая использования calc
// относятся к тому же шаблону функции
template <typename Т> Т calc(const Т&, const Т&); // объявление
template <typename U> U calc(const U&, const U&); // объявление
// определение шаблона
template <typename Type>
Type calc(const Type& a, const Type& b) { /* ... */ }
Конечно, у каждого объявления и определения шаблона должно быть то же количество и вид (т.е. тип или значение) параметров.
По причинам, рассматриваемым в разделе 16.3, объявления всех шаблонов, необходимых данному файлу, обычно располагаются вместе в начале файла перед любым использующим их кодом.
Использование членов типаПомните, как в разделах 7.4 и 7.6 использовался оператор области видимости (::) для обращения к статическим членам и членам типа. В обычном коде (не шаблона) у компилятора есть доступ к определению класса. В результате он знает, является ли имя, к которому обращаются через оператор области видимости, типом или статическим членом. Например, в коде string::size_type, компилятор имеет определение класса string и может узнать, что size_type — это тип.
С учетом того, что Т является параметром типа шаблона, когда компилятор встретит такой код, как T::mem, он не будет знать до времени создания экземпляра, является ли mem типом или статической переменной-членом. Но чтобы обработать шаблон, компилятор должен знать, представляет ли имя тип. Например, если T является именем параметра типа, то как компилятор воспримет следующий код:
T::size_type * p;
Он должен знать, определяется ли переменная по имени p или происходит умножение статической переменной-члена по имени size_type на переменную по имени p.
По умолчанию язык подразумевает, что имя, к которому обращаются через оператор области видимости, не является типом. В результате, если необходимо использовать тип-член параметра типа шаблона, следует явно указать компилятору, что имя является типом. Для этого используется ключевое слово typename:
template <typename Т>
typename Т::value_type top(const T& с) {
if (!c.empty())
return c.back();
else
return typename T::value_type();
}
Функция top() ожидает контейнер в качестве аргумента, она использует ключевое слово typename для определения своего типа возвращаемого значения и создает инициализированный по умолчанию элемент (см. раздел 7.5.3), чтобы возвратить его, если у контейнера с нет никаких элементов.
Когда необходимо уведомить компилятор о том, что имя представляет тип, следует использовать ключевое слово typename, а не class.
Аргументы шаблона по умолчаниюАналогично тому, как можно предоставить аргументы по умолчанию для параметров функции (см. раздел 6.5.1), можно предоставить аргументы шаблона по умолчанию (default template argument). По новому стандарту можно предоставлять аргументы по умолчанию и для шаблонов функций, и для шаблонов классов. Прежние версии языка допускали аргументы по умолчанию только для шаблонов класса.
В качестве примера перепишем функцию сравнения, использующую по умолчанию библиотечный шаблонный объект функции less (см. раздел 14.8.2):
// compare() имеет аргумент шаблона по умолчанию, less<T>
// и заданный по умолчанию аргумент функции, F()
template <typename Т, typename F = less<T>>
int compare(const T &v1, const T &v2, F f = F()) {
if (f(v1, v2)) return -1;
if (f(v2, v1)) return 1;
return 0;
}
Здесь в шаблон добавлен второй параметр типа, F, представляющий тип вызываемого объекта (см. раздел 10.3.2), и определен новый параметр функции, f, который будет связан с вызываемым объектом.

