Код шаблона не компилируется, пока шаблонная функция не используется. Но где это сохраняет скомпилированный код, это сохраняется в объектном файле, от которого использовал шаблонную функцию во-первых?
Например, main.cpp вызывает шаблонную функцию из файла test.h, компилятор генерирует объектный файл main.o, действительно ли шаблонная функция внутри является main.o файлом? потому что код шаблона не встраивается, не так ли?
Это полностью зависит от реализации компилятора. Большинство компиляторов генерируют код вокруг, в строке или в cpp-подобных файлах, а затем компилируют с ним. Иногда, при настройке оптимизации, некоторые компиляторы даже повторно используют один и тот же код вместо того, чтобы создавать его заново для каждого cpp.
Поэтому для получения более подробной информации вам следует обратиться к документации вашего компилятора.
Вы имеете в виду созданный экземпляр, а не скомпилированный. Во время компиляции компилятор обнаруживает каждую версию, которую использует ваш код, и устанавливает (в объектных файлах) все необходимые версии.
Да, код шаблонной функции раскрывается в файле main.o
. Некоторые из них могут быть вставлены, как и любой другой код, но в целом код для шаблонов публикуется в любом файле, в котором шаблон инстанцируется. Считайте, что сначала код шаблона инстанцируется для создания обычных нешаблонных функций, а затем эти функции компилируются с теми инлайнингом и оптимизацией, которые компилятор применяет к любой другой функции.
Когда один и тот же инстанс шаблона (например, std::vector
) встречается в нескольких единицах компиляции (файлы .cpp
), возникает некоторая сложность, поскольку код инстанцируется в каждом из них. Существуют различные способы решения этой проблемы, иногда включающие этап очистки на этапе компоновки, на котором дублирующиеся инстанцирования шаблонов разрешаются в один; руководство вашего компилятора может предоставить более подробную информацию о том, как именно он обрабатывает эту ситуацию.
Код шаблона компилируется, даже если он никогда не создается. В противном случае компиляторы не могли бы потребовать выдачи диагностики для этого:
template< typename T >
void f()
{
blah
}
Компиляция шаблона происходит в двух фазах . Помимо основных проверок, все, что зависит от параметров шаблона, можно проверить только тогда, когда шаблон создан, а формальные параметры заполнены фактическими типами.Например, здесь
template< typename T >
void f()
{
typename T::nested_type x;
}
T :: nested_type
можно проверить только после создания экземпляра шаблона и задания фактического типа для T
. Однако базовая проверка («заданный T :: nested_type
является типом, допустимое ли это определение переменной?») Выполняется в тот момент, когда компилятор встречает определение шаблона. (Вот почему это typename
является обязательным, BTW. В зависимости от T
, T :: nested_type
также может быть именем члена T
или статический член данных - что сделало бы T :: nested_type x;
синтаксической ошибкой. Поэтому мы должны указать компилятору рассматривать T :: nested_type
как имя типа.)
Он всегда встроен (это означает, что это всегда внутренняя ссылка, имеющая встроенную семантику). На самом деле он может быть не встроен в конце концов, так же как встроенная функция, однако шаблон - это не код. Это «шаблон для создания кода». Следовательно, он обычно находится в заголовке, за исключением особых случаев, см. Ниже.
Была идея сделать что-то еще, под кодовым названием «ключевое слово экспорта». Его убрали из стандарта.
Особые случаи: вы можете скомпилировать экземпляры шаблона в объектный файл, не используя их. Это единственный способ избежать встраивания всего кода шаблона. Вот как это делается:
template class std::vector<MyClass>;
Это заставит компилятор создать экземпляр шаблона в текущем месте. В C ++ 0x будет синтаксис, заставляющий компилятор , а не делать это, а компоновщик будет искать экземпляр шаблона в другом месте:
extern template class std :: vector