C++. Сборник рецептов - Д. Стефенс
Шрифт:
Интервал:
Закладка:
указывает, что вы не хотите использовать соглашение об именах Boost, а строка
#include <boost/config/auto_link.hpp>
вызывает pragma comment для поддерживающих ее компиляторов.
Смотри такжеРецепт 1.23.
1.26. Использование экспортируемых шаблонов
ПроблемаВы хотите собрать программу, использующую экспортируемые шаблоны, что означает, что она объявляет шаблоны в заголовочных файлах с использованием ключевого слова export, а реализация шаблонов находится в файлах .cpp.
РешениеВо-первых, скомпилируйте в объектные файлы файлы .cpp, содержащие реализации шаблонов, передав компилятору опцию командной строки, необходимую для включения экспортируемых шаблонов. Затем скомпилируйте и скомпонуйте файлы .cpp, использующие экспортируемые шаблоны, передав компилятору и компоновщику опции командной строки, необходимые для включения экспортируемых шаблонов, а также опции, указывающие директории, содержащие реализации шаблонов.
Опции для включения экспортируемых шаблонов приведены в табл 1.39. Опции для указания расположения реализаций шаблонов приведены в табл. 1.40. Если ваш инструментарий в этой таблице не указан, то он, скорее всего, не поддерживает экспортируемых шаблонов.
Табл. 1.39. Опции для включения экспортируемых шаблонов
Инструментарий Сценарий Comeau (Unix) -export, -A или -strict Comeau (Windows) -export или -A Intel (Linux) -export или -strict-ansi¹¹ Версии компилятора Intel для Linux до 9.0 использовали опцию -strict_ansi
Табл. 1.40. Опции, указывающие расположение реализаций шаблонов
Инструментарий Сценарий Comeau -template_directory=<path> Intel (Linux) -export_dir<path>Например, предположим, что вы хотите скомпилировать программу, показанную в примере 1.27. Она содержит три файла.
• Файл plus.hpp содержит объявление экспортируемого шаблона функции plus().
• Файл plus.cpp содержит определение plus().
• Файл test.cpp включает объявление — но не определение — plus() и определяет функцию main(), использующую plus().
Пример 1.27. Простая программа, использующая экспортируемые шаблоны
plus.hpp:
#ifndef PLUS_HPP_INCLUDED
#define PLUS_HPP_INCLUDED
export template<typename T>
T plus(const T& lhs, const T& rhs);
#endif // #ifndef PLUS_HPP_INCLUDED
plus.cpp:
#include "plus.hpp"
template<typename T>
T plus(const T& lhs, const T& rhs) {
return rhs + lhs;
}
test.cpp:
#include <iostream>
#include "plus.hpp"
int main() {
std::cout << "2 + 2 = " << plus(2, 2) << "n";
}
Чтобы скомпилировать plus.cpp в объектный файл plus.obj с помощью Comeau в Unix, перейдите в директорию, содержащую plus.cpp, plus.hpp и test.cpp, и введите следующую команду.
$ como -c --export plus.cpp
Эта команда также генерирует файл plus.et, описывающий реализацию шаблона, содержащегося в plus.cpp.
Для развлечения откройте plus.et в текстовом редакторе.
Затем скомпилируйте test.cpp в объектный файл test.obj с помощью команды:
$ como -c --export test.cpp
Наконец, скомпонуйте исполняемый файл test.exe.
$ como --export -о test test.obj
Две последние команды также можно объединить в одну.
$ como --export -o test test.cpp
Теперь можно запустить test.exe.
$ ./test
2 + 2 = 4
Теперь предположите, что файлы plus.hpp и plus.cpp находятся в директории с именем plus, a test.cpp находится в дочерней директории test. Чтобы скомпилировать и скомпоновать test.cpp, перейдите в директорию test и введите:
$ como --export --template_directory=../plus -I../plus -o test
test.cpp
ОбсуждениеC++ поддерживает две модели обеспечения определений шаблонов функций и статических данных-членов шаблонов классов: включающую (inclusion model) и раздельную (separation model) модели. Включающая модель знакома всем программистам, регулярно использующим шаблоны С++, но часто оказывается непонятной программистам, привыкшим писать код без шаблонов. Во включающей модели определение шаблона функции — или статических данных-членов шаблона класса — должно включаться в каждый исходный файл, ее использующий. В противоположность этому при использовании нешаблонных функций и данных достаточно включить в исходный файл только объявление; определение может быть помещено в отдельный файл .cpp.
Раздельная модель ближе к традиционной манере организации исходного кода C++. Для шаблонов, объявленных с ключевым словом export, не требуется включать определения во все исходные файлы, их использующие. Вместо этого определения помещаются в отдельные файлы .cpp. Однако параллель с традиционной организацией кода не полная, так как даже несмотря на то, что код, использующий экспортируемый шаблон, не требует включения его определения, он зависит от определения.
Раздельная модель предлагает несколько потенциальных преимуществ.
Уменьшение времени компиляции
Время компиляции при использовании раздельной модели может сократиться благодаря тому, что сканирование определений шаблонов производится реже, и потому, что раздельная модель уменьшает зависимости между модулями.
Снижение «загрязнения» символов
Имена функций, классов и данных, используемых в файле реализации шаблона, могут быть полностью скрыты от кода, использующего этот шаблон, что снижает возможность случайного совпадения имен. Кроме того, автор реализации шаблона может уделять меньше внимания случайным совпадениям с именами из исходных файлов, использующих шаблон
Возможность поставлять скомпилированные реализации шаблонов.
Теоретически при использовании раздельной модели поставщик может распространять реализации шаблонов в скомпилированном двоичном виде, находящемся где-то посередине между исходным кодом C++ и обычными объектными файлами.
Все три потенциальных преимущества раздельной модели спорны. Во-первых, хотя некоторые пользователи сообщали о сокращении времени компиляции, раздельная модель также может в некоторых случаях привести к его увеличению. В настоящее время данных для окончательных выводов недостаточно. Во-вторых, хотя раздельная модель снижает некоторые виды загрязнения символов, правила языка, необходимые для поддержки раздельной модели, и особенно идея двухэтапного поиска, усложняют способ написания кода шаблона — даже по сравнению с включающей моделью - и имеют несколько нежелательных последствий. В-третьих, все существующие реализации раздельной модели основаны на оболочке EDG, a EDG пока еще не предоставляет никаких возможностей для компиляции исходных файлов, содержащих реализации экспортируемых шаблонов, в двоичные файлы, которые могут поставляться вместо исходников.
В 2003 году имела место попытка удалить экспортируемые шаблоны из будущих версий стандарта С++, но она провалилась. Следовательно, экспортируемые шаблоны являются постоянной частью языка С++, и вы должны научиться использовать их.
Смотри такжеРецепт 1.25.
Глава 2
Организация кода
2.0. Введение
Возможно, что одной из причин популярности C++ является его способность одинаково хорошо подходить для маленьких, средних и больших проектов. Для небольшого прототипа или исследовательского проекта можно написать всего несколько классов, а при росте проекта и увеличении числа сотрудников C++ позволяет масштабировать приложение, разбив его на модули, различающиеся по степени своей независимости. Недостатком здесь является то, что вы должны потратить время на то, чтобы вручную выполнить реорганизацию (добавить пространства имен, реорганизовать физическое расположение заголовочных файлов и т.д.). Обычно это стоит того, так как при этом приложение становится модульным и позволяет отдельным людям сосредоточиться только на их локальной функциональной области.