Использование шаблона extern (C++11)
Рис. 1: шаблоны функций
TemplHeader.h
template<typename T>
void f();
TemplCpp.cpp
template<typename T>
void f(){
//...
}
//explicit instantation
template void f<T>();
Главная.cpp
#include "TemplHeader.h"
extern template void f<T>(); //is this correct?
int main() {
f<char>();
return 0;
}
это правильный способ использовать extern template, или использовать это ключевое слово только для шаблонов классов как на рисунке 2?
Рисунок 2: класс шаблоны
TemplHeader.h
template<typename T>
class foo {
T f();
};
TemplCpp.cpp
template<typename T>
void foo<T>::f() {
//...
}
//explicit instantation
template class foo<int>;
Главная.cpp
#include "TemplHeader.h"
extern template class foo<int>();
int main() {
foo<int> test;
return 0;
}
Я знаю, что хорошо поместить все это в один файл заголовка, но если мы создадим шаблоны с одинаковыми параметрами в нескольких файлах, то у нас будет несколько одинаковых определений, и компилятор удалит их все (кроме одного), чтобы избежать ошибок. Как я могу использовать extern template? Мы можем использовать его только для классов, или мы можем использовать его для функций тоже?
кроме того, Рисунок 1 и Рисунок 2 могут быть расширены до решения, где шаблоны находятся в одном файле заголовка . В этом случае нам нужно использовать extern template ключевое слово, чтобы избежать нескольких одинаковых мгновений. Это только для классов или функций тоже?
4 ответов:
вы должны использовать только
extern templateчтобы заставить компилятор не создать экземпляр шаблона, когда вы знаете что он будет создан где-то еще. Он используется для уменьшения времени компиляции и размера объектного файла.например:
// header.h template<typename T> void ReallyBigFunction() { // Body } // source1.cpp #include "header.h" void something1() { ReallyBigFunction<int>(); } // source2.cpp #include "header.h" void something2() { ReallyBigFunction<int>(); }это приведет к следующим объектным файлам:
source1.o void something1() void ReallyBigFunction<int>() // Compiled first time source2.o void something2() void ReallyBigFunction<int>() // Compiled second timeесли оба файла связаны вместе, один
void ReallyBigFunction<int>()будет отброшено, что приведет к потере времени компиляции и объектного файла размер.чтобы не тратить время компиляции и размер выходного файла, есть
externключевое слово, которое заставляет компилятор не компилировать функцию шаблона. Вы должны использовать это если и только если вы знаете он используется в том же двоичном файле где-то еще.изменение
source2.cppto:// source2.cpp #include "header.h" extern template void ReallyBigFunction<int>(); void something2() { ReallyBigFunction<int>(); }приведет к следующим объектным файлам:
source1.o void something1() void ReallyBigFunction<int>() // compiled just one time source2.o void something2() // No ReallyBigFunction<int> here because of the externкогда оба они будут связаны вместе, второй объектный файл будет просто использовать символ из первого объектного файла. Нет необходимости отбрасывать и не тратить впустую время компиляции и размер объектного файла.
это должно использоваться только в рамках проекта, как и в тех случаях, когда вы используете шаблон, как
vector<int>несколько раз, вы должны использоватьexternво всех, кроме одного исходный файл.это также относится к классам и функции как один, и даже функции-члены шаблона.
Википедии есть лучшее описание
В C++03 компилятор должен создавать экземпляр шаблона всякий раз, когда полностью задан шаблон встречаются в переводе. Если шаблон создается с теми же типами в многие единицы перевода, это может значительно увеличить время компиляции. Нет возможности предотвратите это в C++03, поэтому C++11 ввел объявления шаблонов extern, аналогичные extern объявления данных.
C++03 имеет этот синтаксис, чтобы обязать компилятор создать экземпляр шаблона:
template class std::vector<MyClass>;В C++11 теперь предоставляет следующий синтаксис:
extern template class std::vector<MyClass>;который говорит компилятору не инстанцировать шаблон в данной единице трансляции.
предупреждение:
nonstandard extension used...Microsoft VC++ раньше имел нестандартное версия этой функции в течение нескольких лет уже (в C++03). Компилятор предупреждает об этом, чтобы предотвратить проблемы переносимости с кодом, который необходимо скомпилировать на разных компиляторах.
посмотрите на образец в ссылке чтобы увидеть, что он работает примерно одинаково. Вы можете ожидать, что сообщение исчезнет с будущими версиями MSVC, за исключением, конечно, при использовании другое нестандартные расширения компилятора в то же время.
известная проблема с шаблонами-это раздувание кода, которое является следствием генерации определения класса в каждом модуле, который вызывает специализацию шаблона класса. Чтобы предотвратить это, начиная с C++0x, можно использовать ключевое слово extern перед классом шаблон специализации
#include <MyClass> extern class CMyClass<int>;явный экземпляр класса шаблона должен происходить только в одной единице перевода, предпочтительно один с определением шаблона (MyClass.cpp)
template class CMyClass<int>; template class CMyClass<float>;
Если вы раньше использовали extern для функций, то для шаблонов используется точно такая же философия. если нет, то идти хотя extern для простых функций может помочь. Кроме того, вы можете поместить extern(ы) в файл заголовка и включить заголовок, когда вам это нужно.
Comments