Время компоновки / компиляции статических библиотек шаблонов

Кажется, существует общее соглашение не использовать исходные файлы для шаблонных классов (STL и boost), а также помещать реализацию в заголовок. Я предполагаю, что это увеличит время, необходимое для компиляции исходных файлов, которые включают заголовок, по сравнению с классическим разделением между объявлением и реализацией в заголовочных и исходных файлах. Причина, по которой это делается, вероятно, связана с тем, что вам нужно указать компилятору в исходном файле, какие шаблоны использовать, что, вероятно, приведет к раздутому .a файлу.

Предполагая, что компоновщик также требует больше времени по мере роста библиотеки, какой подход будет быстрее с точки зрения времени, необходимого для компиляции исходного файла, который включает заголовок библиотеки?

1. Не использовать файл .cpp и поместить весь класс, включая реализацию, в заголовок

//foo.hpp
template <class T>
class Foo
{
public:
Foo(){};
T bar()
{
T* t = NULL;
//do stuff
return *t;
}
};

или же

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

//foo.h
template <class T>
class Foo
{
public:
Foo(){};
T bar();
};

//foo.cpp
template <class T>
T Foo<T>::bar()
{
T* t = NULL;
//do stuff
return *t;
}

template class Foo<int>;
template class Foo<float>;
template class Foo<double>;
template class Foo<long long>;

5

Решение

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

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

В C ++ 2011 также существует золотая середина: можно сказать компилятору, что определенные экземпляры уже созданы, объявив специализацию как extern, Таким образом, компилятор знает, что ему не нужно создавать экземпляр шаблона с определенными аргументами, но если используются другие аргументы, он знает, что ему нужно их создать. Например, стандартная библиотека C ++ имеет std::basic_string и это может предсказать, что экземпляры для char а также wchar_t могут быть использованы и могут поместить их в библиотеку, объявив экземпляры как extern, Однако наличие легкодоступного кода делает его жизнеспособным для использования std::basic_string<user_type> с пользовательскими типами.

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

4

Другие решения

Обычно компилятор генерирует код один раз для конкретного модуля компиляции, а компоновщик обеспечивает доступ к переменным и функциям другим модулям компиляции.

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

Затем компоновщик также должен знать шаблоны и согласовывать несколько экземпляров одного и того же объекта.

C ++ 11 немного помогает в этом сценарии, где можно объявить:

template class MyTemplate<MyType>;

в одном файле C ++ и затем используйте:

extern template class MyTemplate<MyType>;

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

увидеть Вот для более подробной информации

4

Уже есть два хороших ответа, поэтому я просто напишу вкратце.
Шаблонный код не может быть скомпилирован без бетон типы, вот почему вы не можете сделать классический «компиляция и ссылка».
Шаблонная функция или класс не завершены в том смысле, что не все типы разрешены, пока не будет применено конкретное использование в коде (где определенный тип заменяет шаблон).
По этой причине шаблоны помещаются в заголовочные файлы и не могут быть скомпилированы независимо от конкретного использования.

1
По вопросам рекламы [email protected]