Д. Вандевурд, Н.М. Джосаттис - Шаблоны C++. Справочник разработчика (2003) (1160769), страница 67
Текст из файла (страница 67)
Это означает, что для выполнения такой операции во время выполнения работы программы понадобились бы сведения о том, в каких взаимоотношениях находятся операнды. Для этого создается динамическая структура, представляющая древовидную схему выражения, что является альтернативой шаблонам выражений. Впервые такой подход был применен Робертом Дэвисом (аоЬегг Оащез) в библиотеке ХееМаг [28] задолго до того, как были придуманы шаблоны выражений. Область применения шаблонов выражений не ограничивается только численными расчетами. Их увлекательное использование было предложено, например, Яакко Ярвн ()ааЫсо 1йгч[) и Гэри Пауэллом (Оагу Роже!1) в библиотеке [.ашба 1.!Ьгагу [20[.
В ней функциональные объекты стандартной библиотеки используются как объекты- выражения. Например, благодаря этой библиотеке можно записать такой код: чозс[ 1ашЬда с[елю(вас[::чессог<1опд*>й опев) ( вкс[::вогк(опев.Ьедйп(), опев.ецио(), * 1 > * 2); В приведенном фрагменте кода массив сортируется в порядке возрастания тех значений, на которые ссьиаются его элементы. Если бы не было библиотеки [.шпЬба, пришлось бы создавать несложный, но громоздкий функциональный тип. Однако благодаря библиотеке нужные операторы можно составлять с помощью простого встроенного синтаксиса.
В рассмотренном примере 1 и 2 — это шаблоны-заполнители, предоставляемые библиотекой [.апЬйа. Они соответствуют элементарным объектам-выражениям, которые также являются функторами. С помощью методов, рассмотренных в данной главе, из этих элементарных объектов можно составлять более сложные выражения. 18.4.
Заключение Шаблоны выражений были изобретены независимо Тоддом Вельдхаузеном (То<Ы Че1дЬшхеп), благодаря которому и появился этот термин, и Дэвидом Вандевурдом (1)ачЫ уапбечоогде). Это произошло, когда в языке программирования С++ еще не было шаблонов членов (в то время казалось, что они никогда не будут добавлены в С++). Из-за этого возникали некоторые проблемы, связанные с реализацией оператора присвоения: он не мог быть парамегризован для шаблонов выражений. Один из способов обойти зту проблему состоал в том, чтобы ввести в шаблон выражения оператор преобразования к классу Сорйег.
параметризованному шаблоном выражения, но унаследованному от ба- Глава )Я.Шаблоны выражений Збб зового основного класса, параметризованного только типом элемента. Далее этот базовый класс предоставлял (виртуальный) интерфейс сору Со, на который мог ссылаться оператор присвоения. Ниже этот механизм представлен схематически (имена шаблонов совпадают с использованными в данной главе). Сетр1аге<сурепате Т> с1азз Сорйег1паегбасе (, рцЫйс: чйгсиа1 чо1б сору ао(Аггау<Т, ЯАггау<Т»й) сопзг; ); Гетр1асе<сурепвюе Т, Гурепате Х> с1азз Сорйег : райс СорйегВазе<Т> рцЫйс: Сорйег(Х сопла йх): ехрг(х) () чйггца1 чойс) сору со(Аггау<Т, ЯАггау<Т»й) сопзс ( // Реализация цикла присвоения ) рг1часе: Х сопзс йехрг1 Сешр1аге<гурепате Т, Сурепаше Кер = ЯАггау<Т» с1азз Аггау ( райс: // Делегированный оператор присвоения Аггау<Т, Кер>й орегасог=(СорйегВазе<Т> сопла йЫ ( Ь.сору со(гер); сшар1асе<сурепате Т, Гурепаше А1, аурепате А2> с1азз А пш1С рцЫйс: орегагог Соррйег«Т, А Иц1С<Т, А1, А2» (); При этом в программу добавляется дополнительный уровень сложности, а на обработку шаблонов выражений во время выполнения программы затрачиваются определенные дополнительные ресурсы.
Однако даже с учетом этих замечаний производитель ность полученных программ была на то время впечатляющей. В стандартной библиотеке С++ содержится шаблон класса ча1аггау; предпслашегся "по он будет полезен в приложениях, в которых применщотся методы, использованные в денной главе для разработки шаблона Аггау, Предшественник шаблона ча1аггау был разра- 18.4.
Заключение 367 ботан с учетом того, что на рынке программных продуктов появятся компиляторы, предназначенные для научных расчетоа которые смогуг распознать этот тип и преобразовать использующую его программу в высокопроизводительный машинный код. Такие компиляторы должны были обладать способностью эффективно работать с этим типом, однако они так и не появились (частично из-за того, что рынок программных продуктов в области научных расчетов занимает сравнительно небольшую долю, а частично из-за того, что после реализации класса ча1аггау в виде шаблона проблема усложнилась).
После изобретения метода шаблонов выражений один из его авторов Дзвид Вандевурд (]ЗатЫ Чапдечооп]е) подал в Комитет по стащарппации С++ предложение преобразовать класс ч а1аггау в шаблон йггау, рассмотренный в данной главе (конечно, доработанный с тем, чтобы придать ему все функциональные возможности класса ча1аггау).
Это предложение бьшо первым, в котором планировалось документировать концепцию параметра Кер. До этого фактические массивы, хранящие реальные данные, и псевдомассивы, предназначенные для реализации шаблонов выражений, были разными массивами. Например, в коде пользователи вводилась фунюпш г о о ( ), аргументом которой является объект класса дггау: с]оиЬ1е йоо (Аггау<с[оиЬ1е> сопвса) Тогда ее вызов в виде йоо (1. 2*х) приводил к преобразованию шаблона выршкения в реальный массив с фактическими данными, даже если для выполнения операций с аргументами временный массив не требуется.
Если же в нашем распоряжении есть аргумент Кер, в который можно помесппь шаблон выражения, то функцию й'оо ( ) можно обьявнть так: снгар1асЕ<сурацаШЕ К> доиЬ1е йоо(дггау<с[оиЬ1е, К> сопнса) При этом не будет выполняться никаких преобразований, в которых нет необходимости. Предложение о модификации класса ча1аггау поступило в то время, когда процесс стандартизации С++ уже шел полным ходом.
Чтобы его принять, пришлось бы переписать весь текст документации, касающийся класса ча1аггау. В результате предложение было отклонено, а в документацию были внесены некоторые исправления, позволяющие описывать классы, основанные на шаблонах выражений.
Однако практическое использование этих возможностей намного сложнее, чем рассмотренное в данной главе. На момент написания книги не было известно ни одной реализации этих возможностей, а стандартный класс ча1аггау, вообще говоря, довольно неэффективен при выполнении тех операций, для которых он разработан. Наконец, следует упомянуть, что многие новаторские подходы, рассмотренные в настоящей главе, а также те, что вошли в библиотеку ЗТ[.~, имеют одну общую особенность.
Все они были первоначально реализованы на одном и том же компиляторе — версии 4 компилятора Вог[апг] С++. Он был, вероятно, первым компилятором, благодаря которому шаблонное программирование стало широко распространенным среди Разработчиков, пользующихся С++. 8Т(. (Зшпбяп( Тсшр!аге (.(озвгу), нлн стандартная библиотека шаблонов, кардинально изменила представления о библиотеках С++; позже онв вошла в стандартную библиотеку С++ [18].
Часть |У Нетрадиционное использование шаблонов Шаблоны могут использоваться для разработки тщательно продуманных библиотек элементов, естественным путем объединяемых в одно целое. То же достигается и при разработке нешаблонных библиотек. Однако когда речь идет о простых приложениях, упрощающих обычное программирование, традиционные процедурные нли объектноориентированные библиотеки не всегда оказываются оптимальным решением из-за непропорционально больших накладных расходов.
Препроцессор С позволяет помочь в раде подобных случаев, но он далеко не всегда адекватен стоящей перед программистом задаче. В этой части рассматриваются некоторые задачи, идеальным средством решения которых оказываются шаблоны. ° Схема классификации типов ° Интеллектуальные указатели ° Кортежи ° Функторы Наша цель — продемонстрировать применение обсуждавшихся ранее технологий на практике.
Мы будем комбинировать и модифицировать их для создания полезных, имеющих широкое практическое применение программных компонентов. Тем не менее основная тема остается прежней — шаблоны С++, а не, например, разработка какой-то библиотеки. Поэтому надеемся, что представленный нами код послужит учебным руководством для создателей библиотек, но ни в коем случае не претендуем на то, что этот код — наилучшее решение поставленных задач. Глава 19 Классификация типов Порой весьма полезной может оказаться возможность определения того, является ли параметр шаблона встроенным типом, указателем, классом и т.д. В следующих разделах описана разработка шаблона общего назначения, который позволит определять различные свойства передаваемого ему типа.