Spec-Zone.ru › GCC 10

Далее: Извлечение указателя на функцию из связанного указателя на член-функцию, Предыдущее: Прагмы интерфейса и реализации C++, Выше: Расширения языка C++ [Оглавление][Индекс]

7.5 Где шаблон? ¶

Шаблоны C++ стали первой языковой особенностью, потребовавшей больше интеллекта от среды, чем это традиционно было на системе UNIX. Как-то компилятор и компоновщик должны убедиться, что каждая экземпляризация шаблона появляется ровно один раз в исполняемом файле, если она нужна, и совсем не появляется в противном случае. Существуют два основных подхода к этой проблеме, которые называются моделью Borland и моделью Cfront.

Модель Borland

Borland C++ решил проблему экземпляризации шаблонов, добавив к компоновщику код, эквивалентный общим блокам; компилятор генерирует экземпляры шаблонов в каждом единице трансляции, использующей их, а компоновщик сводит их вместе. Преимущество этой модели заключается в том, что компоновщику нужно только учитывать сами объектные файлы; нет внешней сложности, о которой нужно беспокоиться. Недостатком является увеличение времени компиляции, поскольку код шаблона компилируется многократно. Код, написанный для этой модели, обычно включает определения всех шаблонов в файле заголовков, так как они должны быть видны для экземпляризации.

Модель Cfront

Переводчик AT&T C++, Cfront, решил проблему экземпляризации шаблонов, создав понятие хранилища шаблонов — автоматически поддерживаемого места, где хранятся экземпляры шаблонов. Более современная версия хранилища работает следующим образом: при построении отдельных объектных файлов компилятор помещает любые определения шаблонов и экземпляризации, встреченные в хранилище. Во время компоновки оболочка компоновщика добавляет объекты из хранилища и компилирует любые необходимые экземпляризации, которые ранее не были сгенерированы. Преимущества этой модели — более высокая скорость компиляции и возможность использования системного компоновщика; для реализации модели Borland поставщику компилятора также необходимо заменить компоновщик. Недостатками являются значительно большая сложность, а следовательно, потенциальная возможность ошибок; для некоторых кодов это может быть таким же прозрачным, но на практике это может быть очень сложно при построении нескольких программ в одной директории и одной программы в нескольких директориях. Код, написанный для этой модели, имеет тенденцию отделять определения нелинейных член-шаблонов в отдельный файл, который должен быть скомпилирован отдельно.

G++ реализует модель Borland на целевых платформах, где это поддерживается компоновщиком, включая целевые платформы ELF (например, GNU/Linux), Mac OS X и Microsoft Windows. В противном случае G++ не реализует ни одну из автоматических моделей.

У вас есть следующие варианты обработки экземпляризации шаблонов:

  1. Ничего не делать. Код, написанный для модели Borland, работает нормально, но каждая единица трансляции содержит экземпляры каждого из используемых шаблонов. Дублированные экземпляры будут удалены компоновщиком, но в большой программе это может привести к неприемлемому количеству дублирования кода в объектных файлах или динамически подключаемых библиотеках.

    Дублированные экземпляры шаблона можно избежать, определив явную экземпляризацию в одном объектом файле и предотвратив неявную экземпляризацию компилятора в других объектных файлах, используя объявление явной экземпляризации, используя синтаксис extern template:

    extern template int max (int, int);

    Этот синтаксис определен в стандарте C++ 2011, но поддерживается G++ и другими компиляторами с момента, значительно опережающего 2011 год.

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

    #include "Foo.h"
    #include "Foo.cc"
    
    template class Foo<int>;
    template ostream& operator <<
                    (ostream&, const Foo<int>&);

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

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

  2. Скомпилируйте свой код с -fno-implicit-templates, чтобы отключить неявное создание экземпляров шаблонов и явно экземпляризировать все используемые. Этот подход требует больше знаний о том, какие экземпляры вам нужны, чем другие, но он менее загадочен и позволяет больше контролировать, если вы хотите убедиться, что используются только требуемые экземпляры.

    Если вы используете код модели Cfront, вы, вероятно, сможете обойтись без использования -fno-implicit-templates при компиляции файлов, которые не включают #include определения член-шаблонов.

    Если вы используете один большой файл для экземпляризации, вы можете скомпилировать его без -fno-implicit-templates, чтобы получить все экземпляры, необходимые для явных экземпляризаций (но не другими файлами), без необходимости указывать их также.

    В дополнение к предварительной декларации явных экземпляризаций (с extern), G++ расширил синтаксис экземпляризации шаблонов, чтобы поддержать экземпляризацию данных поддержки компилятора для класса шаблона (т.е. vtable) без экземпляризации каких-либо его членов (с inline) и экземпляризацию только статических данных-членов класса шаблона без данных поддержки или член-функций (с static):

    inline template class Foo<int>;
    static template class Foo<int>;

Далее: Извлечение указателя на функцию из связанного указателя на член-функцию, Предыдущее: Прагмы интерфейса и реализации C++, Выше: Расширения языка C++ [Оглавление][Индекс]

© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-10.5.0/gcc/Template-Instantiation.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API