- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Язык программирования C++. Пятое издание - Стенли Липпман
Шрифт:
Интервал:
Закладка:
Упражнение 16.37. Библиотечная функция max() имеет два параметра функции и возвращает больший из своих аргументов. У этой функции есть один параметр типа шаблона. Можно ли вызвать функцию max(), передав ей аргументы типа int и double? Если да, то как? Если нет, то почему?
Упражнение 16.38. Когда происходит вызов функции make_shared() (см. раздел 12.1.1), следует предоставить явный аргумент шаблона. Объясните, почему этот аргумент необходим и как он используется.
Упражнение 16.39. Используйте явный аргумент шаблона, чтобы сделать возможной передачу двух строковых литералов первоначальной версии функции compare() из раздела 16.1.1.
16.2.3. Замыкающие типы возвращаемого значения и трансформация типа
Применение явного аргумента шаблона для представления типа возвращаемого значения шаблона функции хорошо работает тогда, когда необходимо позволить пользователю определять тип возвращаемого значения. В других случаях обязательное предоставление явного аргумента шаблона налагает дополнительное бремя на пользователя без всяких преимуществ. Например, можно написать функцию, которая получает два обозначающих последовательность итератора и возвращает ссылку на элемент этой последовательности:
template <typename It>
??? & fcn(It beg, It end) {
// обработка диапазона
return *beg; // возвратить ссылку на элемент из диапазона
}
Точный тип, подлежащий возвращению, неизвестен, но известно, что он будет ссылкой на тип элемента обрабатываемой последовательности:
vector<int> vi = {1,2,3,4,5};
Blob<string> ca = { "hi", "bye" };
auto &i = fcn(vi.begin(), vi.end()); // fcn() должна возвратить int&
auto &s = fcn(ca.begin(), ca.end()); // fcn() должна возвратить string&
Здесь известно, что функция возвратит ссылку *beg, а также, что можно использовать выражение decltype(*beg) для получения типа этого выражения. Однако параметр beg не существует, пока не встретится список параметров. Чтобы определить эту функцию, следует использовать замыкающий тип возвращаемого значения (см. раздел 6.3.3). Поскольку замыкающий тип располагается после списка параметров, он может использовать параметры функции:
// замыкающий тип позволяет объявлять тип возвращаемого значения уже
// после списка параметров
template <typename It>
auto fcn(It beg, It end) -> decltype(*beg) {
// обработка диапазона
return *beg; // возвратить ссылку на элемент из диапазона
}
Здесь компилятору было указано, что тип возвращаемого значения функции fcn() совпадает с типом, возвращенным при обращении к значению параметра beg. Оператор обращения к значению возвращает l-значение (см. раздел 4.1.1), таким образом, выведенный выражением decltype тип является ссылкой на тип элемента, обозначаемого параметром beg. Следовательно, если функция fcn() будет вызвана для последовательности строк, то типом возвращаемого значения будет string&. Если это будет последовательность элементов типа int, то возвращен будет тип int&.
Трансформация типа классов библиотечных шаблоновИногда прямого доступа к необходимому типу нет. Например, может возникнуть необходимость в функции, подобной fcn(), которая возвращает элемент по значению (см. раздел 6.3.2), а не по ссылке.
Проблема написания этой функции в том, что о передаваемых типах неизвестно почти ничего. Единственные известные в этой функции операции, которые можно использовать, — это операции с итераторами, и нет никаких операций с итераторами, которые возвращают элементы (в противоположность ссылкам на элементы).
Чтобы получить тип элемента, можно использовать библиотечный шаблон трансформации типа (type transformation). Эти шаблоны определяются в заголовке type_traits. Обычно классы заголовка type_traits используются для так называемого шаблонного метапрограммирования, не рассматриваемого в данной книге. Однако шаблоны трансформации типа полезны и в обычном программировании. Они описаны в табл. 16.1, а их реализация рассматривается в разделе 16.5 (стр. 892).
В данном случае для получения типа элемента можно использовать шаблон remove_reference. У шаблона remove_reference один параметр типа шаблона и (открытый) тип-член type. Если экземпляр шаблона remove_reference создается со ссылочным типом, то тип type будет ссылочным. Например, если создать экземпляр remove_reference<int&>, то типом type будет int. Точно так же, если создать экземпляр remove_reference<string&>, то типом type будет string и т.д. Таким образом, при условии, что beg — итератор, следующее выражение возвратит тип элемента, на который указывает итератор beg:
remove_reference<decltype(*beg)>::type
Выражение decltype(*beg) возвратит ссылочный тип элемента type. Выражение remove_reference::type удаляет ссылку, оставляя тип самого элемента.
Таблица 16.1. Стандартные шаблоны трансформации типа
Для Mod<Т>, где Mod есть Если T есть To Mod<Т>::type есть remove_reference X& или X&& X в противном случае T add_const X&, const X или функция T в противном случае const Т add_l-value_reference X& T X&& X& в противном случае T& add_r-value reference X& или X&& T в противном случае Т&& remove_pointer X* X в противном случае T add_pointer X& или X&& X* в противном случае T* make_signed unsigned X X в противном случае T make_unsigned знаковый тип unsigned Т в противном случае Т remove_extent X[n] X в противном случае T remove_all_extents X[n1][n2]... X в противном случае TИспользуя шаблон remove_reference и замыкающий тип с выражением decltype, можно написать собственную функцию, возвращающую копию значения элемента:
// для использования типа-члена параметра шаблона следует
// использовать typename; см. p. 16.1.3
template <typename It> auto fcn2(It beg, It end) ->
typename remove_reference<decltype(*beg)>::type {
// обработка диапазона
return *beg; // возвратить копию элемента из диапазона
}
Обратите внимание, что тип-член type зависит от параметра шаблона. Таким образом, чтобы указать компилятору, что type представляет тип (см. раздел 16.1.3), в объявлении типа возвращаемого значения следует использовать ключевое слово typename.

