Д. Вандевурд, Н.М. Джосаттис - Шаблоны C++. Справочник разработчика (2003) (1160769), страница 19
Текст из файла (страница 19)
Отладка шаблонов 107 зЫ:: сетт « " ~п1п"; // Окончатель вас)::сегг « ный отчет "вес)::вогс() ой 10 Яогттгасет'в" пав регйогвес) Ьу:~п яогптгасег::сгеат1опв() — сгеатес) ас зсагт певротату сгасегв1п "цр со Яотттгасег::вах 11че() ггасетв ас сЬе вате с1ве (" вах 11че ат втагт « " Ьейоге)йп яогсттасег::авз1дпвепсв()-авв1дпей ап впагп авв1дпвепсв1п Яогптгасег::совраг1зопв(.)-соврагес) аг впатс соврат1вопв~п~п"; « « « « « « « « « « При запуске этой программы выводится достаточно большой объем информации, однако самое интересное содержится в окончательном отчете.
Об одной из реализаций алгоритма вес):: всгг ( ) трассировщик рассказал следующее: згс)::вота() ой 10 ЯогСТтасег'в ыав регйотвед Ьу: 15 тевротату Сгасегв ир Со 12 Ггасегв ап Г)те заве ттве (10 Ьебоге) 33 аззедпвептз 27 совраг1вопв Например, хотя в процессе сортировки в нашей программе были созданы 15 временных трассировщиков, одновременно существовало не более двух дополнительных объектов. Данный трассировшик, таким образом, играет двоякую рольс он показывает, что для стандартного алгоритма вота () не требуется никаких дополнительных функциональных возможностей, кроме имеющихся в трассировщике (например, нет необходимости в операторах == или >), и дает представление о расходе ресурсов на выполнение алгоритма Однако он ничего не говорит о корректности шаблона сортировки.
6.6.5. Интеллектуальные трассировщики Трассировщики относительно просты и эффективны, но они позволяют отслеживать выполнение шаблона только для конкретных входных данных и конкретных функциональных возможностей. Можно не знать, каким условиям должен удовлетворять оператор сравнения, чтобы алгоритм сортировки был корректен, но в нашем примере проверена работа оператора сравнения, который ведет себя точно так же, как "меньше чем" для целочисленных значений. Существуют расширенные варианты трассировщиков, которые иногда называются интеллектуальными трассировщиками (огас1ез или гил-г1те ала1уг(з огас1еп). Это трасси- Глава б. Применение шаблонов на практике 108 ровщнки, подключенные к так называемой машине логического вывода (?л~егелсе еля?ле) — программе, которая может запоминать определенные утверждения и правила, относящиеся к ним, чтобы делать на их основании определенные заключения.
Одна из таких систем, которая применялась к некоторым частям реализации стандартной библиотеки, а именно МЕ?.Аб, рассматривается в 126) ). Интеллектуальные трассировщики обеспечивают возможность в некоторых случаях динамически проверять алгоритмы шаблонов без полного определения подставляемых аргументов шаблона (аргументами являются интеллектуальные трассировщики) или входных данных (для машины логического вывода могут потребоваться некоторые предположения относительно входных данных).
Однако сложность алгоритмов, которые можно проанализировать таким образом, пока еше невелика вследствие ограниченности машин логического вывода, а количество выполняемой при этом работы весьма значительно. Из-за этого мы не будем останавливаться на разработке интеллектуальных трассировщиков, а читателей, которые заинтересовались этим вопросом, отошлем к упомянутой публикации и содержащимся в ней ссылкам. 6.6.6.
Прототипы Выше упоминалось, что трассировщики часто обеспечивают интерфейс, минимально необходимый для тестируемого с их помощью шаблона Если такой минимальный трассировщик не генерирует динамического вывода, его иногда называют лролзотилози (агслееуре). Прототип обеспечивает возможность удостовериться в том, что реалюация шаблона не требует больших синтаксических ограничений, чем предполагалось. Обычно конструкторы шаблона разрабатывают прототипы для всех концепций библиотеки шаблонов.
б.7. Заключение Организация исходного кода в виде заголовочных и .С-файлов представляет собой практическое следствие различных проявлений так называемого правила одного определения (опе-беГзп(г?оп пз!е — 01Ж), которое детально рассматривается в приложении А, '"Правило одного определения". Вопрос о том, какой модели — включения или разделения — следует отдавать предпочтение, достаточно спорный.
Модель включения представляет собой практичное решение, обусловленное в основном существующими реализациями компиляторов С++. Однако первые реализации С++ были другими: включение определений шаблонов было неявным, что создавало некоторую иллзозию ртделенил (см. главу 10, "Инсшнцирование", где дается подробное описание этой первоначальной модели). б Один из авторов этой работы, дэвид Мюллер (Раид Моззег), прлвлмал активное участие в разработке етавдартвой библиотеки С++. В частности, ол сконструировал в реализовал первые вееоплатлвиые контейнеры.
6.8. Резюме 109 В [341 содержится представление точки зрения Бьерна Страуструпа (В)агпе Бпоизппр) на организацию кода шаблонов и рассматривайтся сопутствующие ей проблемы реализации. Это представление, вне всяких сомнений, не является моделью включения. Да, на определенном зтапе процесса стандартизации бытовало мнение, что именно модель включения является единственной жизнеспособной методикой в втой области. Однако после напряженной дискуссии чаша весов начала склоняться в сторону более разъединенной модели, которая в конечном счете оформилась в модель разделения.
В противоположность модели включения зто теоретическая модель, не основанная ни на каких существующих реализациях, и прошло более пяти лет, прехще чем появилась ее первая опубликованная реализация в мае 2002 года. Иногда заманчиво вообразить себе такое расширение концепции предварительно компилируемых заголовочных файлов, когда в одном процессе компиляции могут загружаться несколько предварительно скомпилированных заголовочных файлов. Это обеспечило бы более тонкий подход к предварительной компиляции. Основным препятствием в данном вопросе является препроцессор: макрос в одном заголовочном файле может полностью изменить смысл последующих заголовочных файлов, а после того как файл откомпилирован и завершена обработка макросов, очень сложно внести какие-либо исправления, связанные с влиянием на препроцессор других заголовочных файлов.
Достаточно удачная попытка улучшить диагностику компилятора С++ путем добавления фиктивного кода в шаблоны высокого уровня содержится в Сопсерг СЬеск 1.1Ьгагу Джереми Сика (1егешу Б)ск) [31, являющейся частью библиотеки Воозг [5].
6.8. Резюме- Шаблоны представляют очень сложную проблему для классической модели компилятор+компоновщик, позтому имеются различные способы организации кода шаблонов: модель вкшочення, явное инстанцирование шаблонов и модель разделения. Обычно следует использовать модель включения (т.е.
размещать весь код шаблонов в заголовочных файлах). Разделение кода шаблонов в различных заголовочных файлах (отдельно объявления и определения) позволяет более легко переключаться между моделью включения и явным инстанцированием. В стандарте С++ определена раздельная модель компиляции шаблонов (с использованием ключевого слова ехрохс)„которая, однако, в настоящее время не имеет широкого распространения.
Отладка кода шаблонов сопряжена с рядом проблем. Экземпляры шаблонов могут иметь чрезвычайно длинные имена. Чтобы воспользоваться преимуществами применения предварительно откомпилированных заголовочных файлов, следует убедиться в том, что в разных файлах программы соблюдается один и тот же порядок следования директив й зпс1ийе. Глава 7 Основные термины в области шаблонов Предыдущие главы книги были посвящены знакомству с основами концепций шаблонов в С++. Теперь, прежде чем перейти к более подробному рассмотрению шаблонов, хотелось бы уделить внимание терминам, которые используются при изложении материала В этом есть необходимость, поскольку в сообществе С++ (и даже в рамках стандарта) четкое понимание концепций и терминологии отсутствует.
7.1. "Шаблон класса" или "шаблонный класс" В С++ структуры, классы и объединения имеют общее название шипы «яасссь Без дополнительного уточнения слово "класс" обычно служит для обозначения типов класса, заланных с помощью ключевых слов с1авв или вскисс . Особо следует отметить, что з понятие "тип класса" включает объединения, а "класс" — нет.
Существует некоторая путаница в отношении того, как следует именовать класс, являющийся шаблоном. ° Термин шаблон «ласса (с1ава гетр1асе) означает, что класс является шаблоном. Другими словами, это параметризованное описание семейства классов. ° Термин шаблонный класс ()ещр!аге с1азз), с другой стороны, используется ° как синоним для шаблона класса; ° для обозначения классов, сгенерированных из шаблона; 1 В С++ единственное различие между с1авв и встисс заключается в том, что доступ по умолчанию лля класса является закрытым (ркзтасе), в то время как доступ по умолчанию к членам структуры — открытым (рпЬ11с). Однако мы предпочитаем использовать с1авв для типов, я которых применяются новые возможности С++, а вскисс — для обычных структур С, которые могут использоваться как "простые старце данные" (р1юп о1д с)ага — РОВ).
112 Глава 7. Основные термины в области шаблонов ° для обозначения классов с именем, которое является идентификатором шаблона Разница между вторым и третьим значениями весьма незначительна и в остальной части книги не играет сколько-нибудь заметной роли. Из-за упомянутой неточности в данной книге мы старались избегать термина ишбланный класс. Аналогично, мы используем термины шаблон функции (бзпсгюп Гешр1аю) и шаблон функции-члена (шешЬег Гапсбоп сешр1аге), но стараемся избегать терминов шаблонная функция (сешр!аге бгпсг!оп) и шаблонная функция-член (гегар!аге тешЬег гипс!!оп). 7.2.