- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Язык программирования C++. Пятое издание - Стенли Липпман
Шрифт:
Интервал:
Закладка:
Следует заметить, что хеш-функция определена для хеширования всех трех переменных-членов, чтобы она была совместима с определением оператора operator== класса Sales_data (см. раздел 14.3.1). По умолчанию неупорядоченные контейнеры используют специализацию хеша, соответствующую типу key_type, наряду с оператором равенства типа ключа.
С учетом того, что специализация находится в области видимости, она будет использоваться автоматически при использовании класса Sales_data как ключ в одном из этих контейнеров:
// использует hash<Sales_data> и оператор operator== класса Sales_data
// из раздела 14.3.1
unordered_multiset<Sales_data> SDset;
Поскольку hash<Sales_data> использует закрытые члены класса Sales_data, этот класс следует сделать другом класса Sales_data:
template <class T> class std::hash; // нужно для объявления
// дружественным
class Sales_data {
friend class std::hash<Sales_data>;
// другие члены, как прежде
};
Здесь указано, что специфический экземпляр hash<Sales_data> является дружественным. Поскольку данный экземпляр определяется в пространстве имен std, следует помнить, что этот тип хеша определяется в пространстве имен std. Следовательно, объявление friend относится к std::hash.
Чтобы позволить пользователям класса Sales_data использовать специализацию шаблона hash, следует определить эту специализацию в заголовке Sales_data.
Частичная специализация шаблона классаВ отличие от шаблона функции, специализация шаблона класса не обязана предоставлять аргументы для каждого параметра шаблона. Можно определить некоторые из них, но не все.
Частичная специализация (partial specialization) шаблона класса сама является шаблоном. Пользователи должны предоставить аргументы для тех параметров шаблона, которые не затронуты специализацией.
Частично можно специализировать только шаблон класса. Нельзя частично специализировать шаблон функции.
Библиотечный тип remove_reference был представлен в разделе 16.2.3, он работает с серией специализаций:
// первоначальный, наиболее общий шаблон
template <class Т> struct remove_reference {
typedef T type;
};
// частичные специализации, которые будут использоваться для ссылок
// на l- и r-значения
template <class Т> struct remove_reference<T&> // ссылки на l-значение
{ typedef Т type; };
template <class T> struct remove_reference<T&&> // ссылки на r-значение
{ typedef T type; };
Первый шаблон определяет самую общую версию. Его экземпляр может быть создан с любым типом; он использует свой аргумент шаблона как тип для своего члена type. Следующие два класса — это частичные специализации первоначального шаблона.
Поскольку частичная специализация — это шаблон, начнем, как обычно, с определения параметров шаблона. Подобно любой другой специализации, у частичной специализации то же имя, что и у специализируемого шаблона. Список параметров специализации шаблона включает элементы для каждого параметра шаблона, тип которого не был определен полностью при частичной специализации. После имени класса располагаются аргументы для параметров специализируемого шаблона. Эти аргументы располагаются в угловых скобках после имени шаблона. Аргументы позиционально соответствуют параметрам первоначального шаблона.
Список параметров шаблона частичной специализации — это подмножество или специализация списка параметров первоначального шаблона. В данном случае у специализаций то же количество параметров, что и у первоначального шаблона. Но тип параметров в специализациях отличается от первоначального шаблона. Специализация будут использоваться для ссылок на типы l- и r-значений соответственно:
int i;
// decltype(42) - это int, используется первоначальный шаблон
remove_reference<decltype(42)>::type a;
// decltype(i) - это int&, используется первая (Т&) частичная
// специализация
remove_reference<decltype(i)>::type b;
// decltype(std::move(i)) - это int&&, используется вторая (т.е., T&&)
// частичная специализация
remove_reference<decltype(std::move(i))>::type c;
У всех трех переменных, a, b и с, тип int.
Специализация членов, но не классаВместо специализации всего шаблона можно специализировать только одну или несколько его функций-членов. Например, если Foo — это шаблон класса с членом Bar, можно специализировать только этот член:
template <typename Т> struct Foo {
Foo (const T &t = T()): mem(t) { }
void Bar() { /* ... */ }
T mem;
// другие члены класса Foo
};
template<> // специализация шаблона
void Foo<int>::Bar() // специализация члена Bar класса Foo<int>
{
// осуществить всю специализированную обработку, относящуюся к целым
// числам
}
Здесь специализируется только один член класса Foo<int>. Другие его члены предоставляются шаблоном Foo:
Foo<string> fs; // создает экземпляр Foo<string>::Foo()
fs.Bar(); // создает экземпляр Foo<string>::Bar()
Foo<int> fi; // создает экземпляр Foo<int>::Foo()
fi.Bar(); // использует специализацию Foo<int>::Bar()
При использовании шаблона Foo с любым типом, кроме int, члены экземпляра создаются, как обычно. При использовании шаблона Foo с типом int все члены экземпляра, кроме Bar, создаются, как обычно. Если использовать член Bar класса Foo<int>, то получится специализированное определение.
Упражнения раздела 16.5Упражнение 16.62. Определите собственную версию класса hash<Sales_data> и контейнер unordered_multiset объектов класса Sales_data. Поместите в контейнер несколько транзакций и выведите его содержимое.
Упражнение 16.63. Определите шаблон функции для подсчета количества вхождений заданного значения в векторе. Проверьте программу, передав ей вектор значений типа double, вектор целых чисел и вектор строк.
Упражнение 16.64. Напишите специализированную версию шаблона из предыдущего упражнения для обработки вектора vector<const char*> и используйте ее в программе.
Упражнение 16.65. В разделе 16.3 были определены две перегруженных версии функции debug_rep(), одна из которых получает параметр типа const char*, а вторая — типа char*. Перепишите эти функции как специализации.
Упражнение 16.66. Каковы преимущества и недостатки перегрузки функций debug_rep() по сравнению с определением специализаций?
Упражнение 16.67. Повлияет ли определение этих специализаций на подбор функций debug_rep()? Почему?
Резюме
Шаблоны — это отличительная особенность языка С++ и основа его стандартной библиотеки. Шаблон представляет собой независимый от типа "чертеж", используемый компилятором для создания конкретных экземпляров указанных классов или функций. Шаблон разрабатывается один раз, а его экземпляры компилятор создает для соответствующего типа или значения по мере его применения.
Можно определять шаблоны функций и классов. Библиотечные алгоритмы являются шаблонами функций, а библиотечные контейнеры — шаблонами классов.
Явный аргумент шаблона позволяет фиксировать тип или значение одного или нескольких параметров шаблона. К параметрам с явным аргументом шаблона применимы нормальные преобразования.
Специализация шаблона — это отдельное специальное определение, позволяющее создать такую версию шаблона, в которой для одного или нескольких параметров указан определенный тип или значение. Специализация полезна в случае, когда для некоторых типов стандартное определение шаблона неприменимо.
Главная часть последнего выпуска стандарта языка С++ относится к шаблонам с переменным количеством аргументов. Такой шаблон способен получать переменное количество аргументов разных типов. Шаблоны с переменным количеством аргументов позволяют написать такие функции, как функция-член emplace() классов контейнеров и библиотечная функция make_shared(), передающая аргументы конструктору объекта.
Термины

