Д. Вандевурд, Н.М. Джосаттис - Шаблоны C++. Справочник разработчика (2003), страница 10
Описание файла
DJVU-файл из архива "Д. Вандевурд, Н.М. Джосаттис - Шаблоны C++. Справочник разработчика (2003)", который расположен в категории "". Всё это находится в предмете "языки программирования" из 7 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Просмотр DJVU-файла онлайн
Распознанный текст из DJVU-файла, 10 - страница
В этом случае, как и для шаблонов с параметрами типа, программист создает код, в котором определение отдельных деталей откладывается "на потом", т.е. до момента, когда код будет использоваться; однако зги детали представляют собой уже не типы, а величины. При использовании шаблона эти величины задаются явно, после чего выполняется инстанцирование кода шаблона. В данной главе эта возможность продемонстрирована на примере новой версии шаблона класса стека. Кроме того, здесь приведен пример параметров шаблона функции, не являющихся типами, и рассмотрены некоторые ограничения применения этой технологии.
4.1. Параметры шаблонов классов, не являющиеся типами В отличие от примеров реализаций стека из предыдущих глав, стек можно реализовать и на базе массива с фиксированным размером, в котором будут храниться элементы. Преимущество этого метода состоит в сокращении расхода ресурсов на управление памятью, независимо от того, выполняет ли зто управление программист или стандартный контей- неР Однако возникает другая проблема: какой размер для такого стека будет оптимальнымз Если указать размер, меньший, чем требуется, зто приведет к переполнению стека Если запать слишком большой размер, память будет расходоваться неэффективно.
Напрашивжтся вполне резонное решение: оставить определение этого значения на усмотрение "ользователя — он должен указать максимальный размер, необходимый лля работы именно с его элементами. Определим для этого размер в качестве параметра шаблона. // Ьазйсз/зкаск4.ЬРР ййпс1ибе <зЫехсерс> сежр1аке <Сурепате Т, йпе ИАХЯ1ЕЕ> Глава 4. Параметры шаблонов, не являющиеся типами 58 // Элементы // Их текущее количество рцЬ11с: ЯгасК(); чо16 ривЬ(Т сопвгй); чо1с) рор(); Т Гор() сопзг; Ьоо1 ешрсу() сопвс ( гегигп пишЕ1ешв == Ьоо1 йц11() сопзе ( гегцгп пшпЕ1ешз == МАХЯ1ЕЕ; // Возвращается его, // если стек заполнен // Конструктор Гещр1апе <Сурепаще Т, Тпг МАХЯ1ЕЕ> ЯпасК<Т,МАХЯ1ЕЕ>::ЯсасК() пшпЕ1ещв(0) // В начале // в стеке нет элементов // Больше ничего не делается ] сешр1аге <Сурепаше Т, 1пс МАХЯ1ЕЕ> чоЫ ясасК<Т,МАХБ1ЕЕ>::ривЬ(Т сопвгй е1етп] ( 1Й (пшпЕ1ещв == МАХЯ1ЕЕ) ( гЬгои згй::оцс ой галде("ясасК<>::рцвЬ(): всасК" Тз йи11"); е1ешз[пцшЕ1ещв] = е1еш; // Добавление элемента // з конец массива ++пцшЕ1ешз; // Увеличение числа элементов // на 1 Гешр1асе <сурепаще Т, 1пс МАХЯ1ЕЕ> чоЫ ЯсасК<Т,МАХЯ1ЕЕ>::рор() ( Тй (пшяЕ1ешз <= О) ( еЬгощ згс]::оис ой галде("ясасК<>::рор(): ешрсу" вгасК"); с1авз ЯгасК ( рг1часе: Т е1ещв[МАХЯ1ЕЕ]) Хпг пшпЕ1ещв; // // // // // // Ор // Конструктор Добавление элемента Снятие элемента Возвращение элемента с вершины стека Возвращается Ггце, если стек пуст 4,(.
Параметры шаблонов классов, не являющиеся типами 59 --пшвЕ1ешв; // Уменьшение // числа элементов на 1 Сешр1асе <сурепке Т, 1пг МАХЯ12Е> Т ЯсасК<Т,МАХЯ12Е>::Сор() сопвс ( Н (пшаЕ1ешз <= 0) ( СЬГОМ ВГС)::Оиг Об ГандЕ("ЯсаСК<>:глср(): Емреу" вгасК"); ) гесцгп е1евв[пшъЕ1ешз-1];// Возврат последнего элемента ] Новый второй параметр шаблона МАХЯ12Е имеет тип Тпе.
Он задает размер массива элементов стека. семр1аге <куренное Т, 1пс мАХЯ12Е> с1авв ЯсасК ( рг1часе: Т е1ешз[МАХЯ12Е]; // Элементы Кроме того, он задействован в функции рцвЬ ( ) для проверки заполненности стека. сешр1аее <Сурепке Т, 1пг МАХЯ12Е> чоЫ ЯсасК<Т,МАХЯ12Е>::рив)т(Т сопвса е1еш) ( 1б (пшвЕ1ешв == МАХЯ12Е) ( айком "ЯсасК<>::рцвЬ(): всасК 1в бц11"; е1ешв[пшвЕ1ешз] = е1ет/ //' Добавление элемента в // конец массива ++пишЕ1ешв // Увеличение числа элементов Для того чтобы использовать этот шаблон класса, следует задать как тип элементов, так и максимальный размер стека.
// Ьазйсв/зеасК4геве.срр ()1пс1цс)е <1овсгеаш> ()1пс1цс)е <всг1пд> ()Тпс1цс(е <свес)11Ь> ()Тпс1цс)е "всасК4.)трр" Тпс ла1п() Глава 4. Параметры шаблонов, не являющиеся типами ЯеасК<вМ::всгйпд,40> всгйпдЯсасК; // Стек, вмещающий до 40 // строк // Работа со стеком из 20 целых чисел 1пс20ясасК.рцв)т(7); вес)::соне « 1пс20ЯсасК.сор() « вМ::епс)1; 1пе20Яеас1<.рор()' // Работа со стеком из 40 строк всгйпдЯсасК.рцв)з("Ье11о"); вЫ::соне « вегйпдяеасК.сор() « вес)::епд1; всгйпдЯЕасК.рор(); вегйпдЯГасК.рор(); ) саес)з (всг)::ехсере1оп сопвеа ех) ( вес)::сегг « "ехсерейоп: " « ех.ы)зас() « зес(::епс)1; гегцтп ЕХ1Т РАХМАНЕ; // Выход из программы // с указанием ошибки Заметим, что каждый экземпляр шаблона имеет свой собственный тип, т.е.
Епс20ЯеасК и Епг40ЯСасК вЂ” это два различных типа Преобразование этих типов один в другой — ни явное, ни неявное — не определено. Следовательно, нельзя использовать один тип вместо другого и нельзя присваивать значение одного из этих типов другому. Остается добавить, что для параметров данного шаблона можно задать значения по умолчанию. Сешр1асе <Сурепаше Т - "1пе, Епе МАХЕ?ЕЕ = 100> с1авв ЯсасК ( Однако в контексте грамотного дизайна это не имеет смысла. Значения по умолчанию — это значения, которые интуитивно подходят в общем случае; но нельзя сказать, что тип Тпс или максимальный размер, равный 100, в общем случае для типа стека подходят лучше, чем другие. Следовательно, оба эти значения программист должен указывать явно. ( агу ( ЯеасК<1пг,20> Епе20ЯСасК; // Стек, // целых ЯгасК<йпп,40> Епе40ЯСасК; // Стек, // целых вмещающий до'20 значений вмещающий до 40 значений 4,2. Параметры шаблонов функций, не являющиеся типами 61 4.2. Параметры шаблонов функций, не являющиеся типами Параметры, не являющиеся типами, можно использовать и в шаблонах функций.
Например приведенный ниже шаблон функции определяет группу функций, предназначенных для добавления некоторого значения. // Ьавйсв/ас)бча1. Ьрр Сещр1аге <Сурепаще Т, Тпс ЧАЬ> Т ас)НЧа1це (Т сопвгй х) ( гегцгп х + ЧА1„. ) функции такого типа полезны тогда, когда функции или, в общем случае. операции используются в качестве параметров.
Например, при работе со стандартной библиотекой шаблонов экземпляр этого шаблона функции можно использовать для добавления определенного значения к каждому элементу коллекции. всс):гггапвйогш(воигсе.Ьедйп() воигсе.епс)(), с)евг. Ьед1п(), // Начало и конец // исходной коллекции // Начало результирующей // коллекции ас)НЧа1це<йпс,5>); // Операция Существует предложение изменить стандарт С++ таким образом, чтобы в данном «онтексте не требовалось приведение типов [1)), однако сегодня для обеспечения переносимости явное приведение типов необходимо. Последний аргумент вызывает инстанцирование шаблона функции ас)с)Ча1це, которая лобавляет 5 к целочисленному значению.
Полученная функция вызывается для каждого элемента исходной коллекции воигсе, в процессе чего последняя преобразуется в результирующую коллекцию с)ев с. Заметим, что в этом примере проявляется следующая проблема: ас)ЙЧа1ие<1пс, 5> — это шаблон функции, который интерпретируется как имя семейства перегруженных функций (даже если это семейство состоит всего из одного элемента) Олнако в соответствии с текущим стандартом семейства перегруженных функций нельзя использовать при выводе аргументов шаблона. Таким образом, аргумент шаблона фУнкции необходимо привести к точному типу. всс):гегапвйогш(воигсе.Ьедйп(), // Начало и конец воигсе.епд(), // исходной коллекции с)евГ.Ьедйп(), // Начало результирующей // коллекции (1пс ( *) (1пс сопвга) )ас)НЧа1ие<1пс, 5>); // Операция Глава 4. Параметры шаблонов, не являющиеся типами 62 4.3. Ограничения на параметры шаблонов, не являющиеся типами На параметры шаблонов, не являющиеся типами, накладываются некоторые ограничения.
В общем случае такими параметрами могут быть только целочисленные константы (включая перечисления) или указатели на объекты с внешним связыванием. Использование чисел с плавающей точкой и объектов с типом класса в качестве параметров шаблона не допускается. // ОШИБКА: значения с // плавающей точкой нельзя // применять в качестве // параметров шаблона Еешр1асе <дочЬ1е ЧАТ> с)оиЬ1е ргосевв(с)опЬ1е.ч) гесигп ч ь ЧАТ; // ОШИБКА: объекты типа // класса не разрешается // испольэовать как // параметры шаблона Гешр1асе <всс)::вггйпБ паше> с1авв МуС1авв ): / сешр1аге <сЬаг сопвс* паше> с1авв МуС1авв ( МуС1авв<"Ье11о"> ху // ОШИБКА: строковый литерал "Ье11о" // здесь использовать нельзя Нельзя также использовать для этой цели и глобальныйуказатель.
сешр1аге есЬаг сопят* пате> с1авв МуС1авв сЬаг сопле* в = "Ье11о"; МуС1аввев> х; // ОШИБКА: в — указатель на объект // со внутренним связыванием Числа с плавающей точкой (как и литеральные выражения с плавающей точкой) нельзя применять исключительно по причинам исторического характера. Поскольку для этого нет серьезных технических препятствий, в будущих версиях С++ такая возможность, вероятно, станет поддерживаться (см. раздел 13.4, стр. 235). Поскольку строковые литералы — это объекты с внутренним связыванием (два строковых литерала, которые имеют одинаковые значения, но находятся в разных модулях, являются разными объектами), их использование в качестве аргументов шаблона не допускается.
4.4. Резюме 63 Однако приведенный ниже код допустим. сеар1асе <с1зак сопвс* паве> с1авв МуС1авв ( ехсекп сЬак сопвс в 11 = "Ье11о"з МуС1авв<в> х; // ОК Поскольку здесь глобальный массив символов в инициализируется значением "Ье11о", он является объектом с внешним связыванием. Более подробно этот вопрос рассмотрен в разделе 8.3.3, стр. 133, а возможные изменения в данной области в будущем обсуждаются в разделе 13,4, стр. 235. 4.4.
Резюме ° В качестве параметров шаблонов могут выступать не только типы, но и значения. ° В качестве аргументов для параметров шаблонов, не являющихся типами, нельзя использовать числа с плавающей точкой, объекты типа класса и объекты с внутренним связыванием (такие, как строковые литералы). Глава 5 Основы работы с шаблонами В данной главе продолжается рассмотрение основных свойств шаблонов и практических приемов работы с ними. Здесь обсуждаотся следующие вопросы: дополнительные возможности применения ключевого слова сурепатае, использование шаблонов функций- членов и вложенных классов, шаблонные параметры шаблонов, инициализация нулем и некоторые детали, касающиеся использования строковых литералов в качестве аргументов шаблонов функций. Упомянутые аспекты не всегда можно отнести к числу простых н очевидных, однако программист-практик должен иметь хотя бы представление о них.