Программирование >>  Обобщенные обратные вызовы 

1 ... 13 14 15 [ 16 ] 17 18 19 ... 84


Задача 9. Ограничения экспорта.

Часть 1: основы Сложность: 7

Разберемся с export - что о нем думают, что это такое на самом деле и почему все так старательно игнорируют эту возможность.

Вопрос для новичка

1. Что подразумевается под моделью включения для шаблонов? Вопрос для профессионала

2. Что подразумевается под моделью разделения для шаблонов?

3. В чем заключаются основные недостатки модели включения:

а) для обычных функций?

б) для шаблонов?

4. Как можно преодолеть недостатки из вопроса 3 при помощи стандартной модели разделения С+ + :

а) для обычных функций?

б) для шаблонов?

Решение

Стандартная возможность экспорта шаблонов зачастую оказывается неверно понятой, так что данная и следующая задачи призваны исправить ситуацию и внести ясность в этот вопрос.

На момент написания этого материала возможность экспорта поддерживалась только в одном коммерческом компиляторе. Компилятор Comeau , выпущенный в 2002 году и основанный на реализации С++ Edison Design Group (EDG)*, был первым (и пока единственным) компилятором с поддержкой экспорта. Поэтому не удивительно, что у программистов мало опыта по применению экспорта в реальных проектах; впрочем, ситуация должна кардинально измениться с появлением других компиляторов с поддержкой экспорта.

Вот о чем мы поговорим в этой и следующей задачах.

Что такое экспорт и как следует его использовать.

Задачи, для которых предназначается экспорт.

Текущее состояние проблемы.

Как экспорт влияет (зачастую неочевидно) на другие (на первый взгляд, никак не связанные с экспортом) части языка С+ + .

Советы по эффективному использованию экспорта.

Рассказ о двух моделях

Стандарт С++ поддерживает две различные модели организации исходного текста шаблонов: старую, давно используемую модель включения и относительно новую модель разделения.

www.comeaucomputing.com.

www.edg.com.



1. Что подразумевается под моделью включения для шаблонов?

В модели включения (inclusion model) код шаблона с точки зрения исходного текста выглядит так же, как и встраиваемый (inline) (хотя в действительности код шаблона не обязательно должен быть встраиваемым). Весь исходный текст шаблона должен быть видимым для любого кода, который использует этот шаблон. Такая модель называется моделью включения, поскольку обычно при этом для включения заголовочных файлов с определениями шаблонов используются директивы #include .

Если вы знакомы с современными шаблонами С+ + , то вы знакомы и с моделью включения. Это единственная реально используемая модель, хотя бы просто потому, что в настоящее время компиляторы С++ поддерживают только ее. Все шаблоны, с которыми вы сталкивались в реальных программах, книгах и статьях до этого времени, относятся к категории модели включения.

2. Что подразумевается под моделью разделения для шаблонов?

С другой стороны, модель разделения (separation model) предназначается для того, чтобы позволить разделить компиляцию шаблонов (кавычки в данном случае использованы не случайно). В модели разделения определения шаблонов не обязательно должны быть видимы для вызывающих функций. Так и хочется добавить - как и определения обычных функций , но это было бы не верно - несмотря на определенную схожесть, это принципиально разные вещи, как .мы вскоре убедимся. Модель разделения относительно нова - она была добавлена в стандарт в средине 1990-х годов, но первая коммерческая реализация (EDG) появилась только летом 2002 года .

Самое главное при рассмотрении моделей включения и разделения - это понимать и помнить, что это разные модели организации исходного текста программы. Это не разные модели инстанцирования шаблонов, т.е. в любом случае компилятор выполняет одну и ту же работу по настройке шаблонов для конкретных аргументов. Это важно, поскольку именно в этом заключаются причины определенных ограничений экспорта (которые зачастую оказываются неожиданными для профаммистов, в особенности тех, кто прибегает к экспорту, полагая, что это позволит ускорить процесс сборки профам-мы - как в случае раздельной компиляции обычных функций). При использовании любой модели компилятор вправе выполнить оптимизацию, в частности, основанную на правиле одного определения (One Definition Rule - OCR), инстанцируя шаблоны для каждой уникальной комбинации аргументов шаблонов только по одному разу, независимо от того, сколько раз и где эта комбинация встречается в вашей профаммс. Разработчики компиляторов имеют возможность реализовать такую оптимизацию и стратегию инстанцирования независимо от того, какая именно модель --- включения или разделения - используется для физической организации исходных текстов шаблонов. Хотя для модели разделения возможность такого рода оптимизации очевидна, то же самое можно осуществить и при использовании модели включения.

Пояснение на примере

3. В чем заключаются основные недостатки модели включения:

а) для обьиных функций?

б) для шаблонов?

Или, что по сути то же самое, определения размещаются в отдельном . срр-файле. который в свою очередь включается в заголовочный . h-файл.

Заметим, что Cfront имел похожую функциональность за десятилетие до этого. Однако реализация Cfront была медленной и основывалась на эвристике, которая при проблемах, связанных с шаблонами, просто сбрасывала кэш готовых настроенных шаблонов и начинала ин-станцирование всех шаблонов с нуля.



Рассмотрим пример кода шаблона функции как в модели включения, так и в модели разделения. Для сравнения я также привожу обычную функцию - как встраиваемую и в обычном варианте раздельной компиляции; это поможет нам понять отличия между раздельной компиляцией обычных функций и раздельной моделью шаблонов функций. Это совершенно разные вещи, несмотря на то, что в их названиях использовано одно и то же слово раздельный . Именно по этой причине я брал слово раздельный в кавычки.

Рассмотрим следующий код с обычной встраиваемой функцией и шаблоном функции в модели включения.

Пример 9-3(а): встраиваемая функция

- Файл f.h, предоставляемый пользователю - namespace Myiib {

inline void f( int ) {

изящный код, воплотивший в себя годы работы;

использует вспомогательные классы и функции

Ниже приведена демонстрация использования модели включения для шаблонов:

Пример 9-3(6): простенький шаблон, использующий модель

включения

- Файл g.h, предоставляемый пользователю - namespace MyLib {

tempiate<typename т> void gC т& ) {

Изящный код - результат многих лет работы; использует вспомогательные классы и функции, которые не обязательно объявлены как встраиваемые, но их код располагается здесь же, в этом же файле

В обоих случаях код примера 9-3 вызывает вопросы, знакомые для профаммистов на С++.

Открытие исходного текста определений. Теперь определения функций f и g (которые, возможно, представляют предмет патентного права или имеют другие причины быть скрытыми) становятся доступны любому программисту. Само по себе это может и не быть такой уж большой неприятностью, но об этом несколько позже.

Зависимости исходного текста. Все функции, вызывающие f или д, зависят от деталей их внутреннего устройства, так что при любом внесении изменений в f или 9 требуется перекомпиляция всего кода, который к ним обращается. Кроме того, если в теле f или g используются типы, которые не упоминаются в объявлениях этих функций, то в результате вызывающие их функции также требуют доступа к полным определениям этих типов.

Использование экспорта

В состоянии ли мы решить (или хотя бы уменьшить) эти проблемы?

4. Как можно преодолеть недостатки из вопроса 3 при помощи стандартной модели разделения С++:

а) для обычных функций?



1 ... 13 14 15 [ 16 ] 17 18 19 ... 84

© 2006 - 2025 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки.
Яндекс.Метрика