150 votes

en utilisant un modèle externe (C ++0x)

Figure 1: les modèles de fonction

TemplHeader.h

template<typename T>
void f();

TemplCpp.cpp

template<typename T>
void f(){
   //...
}    
//explicit instantation
template void f<T>();

Main.cpp

#include "TemplHeader.h"
extern template void f<T>(); //is this correct?
int main() {
    f<char>();
    return 0;
}

Est-ce la bonne façon d'utiliser des extern template, ou dois-je utiliser ce mot-clé uniquement pour les modèles de classe comme dans la Figure 2?

Figure 2: modèles de classe

TemplHeader.h

template<typename T>
class foo {
    T f();
};

TemplCpp.cpp

template<typename T>
void foo<T>::f() {
    //...
}
//explicit instantation
template class foo<int>;

Main.cpp

#include "TemplHeader.h"
extern template class foo<int>();
int main() {
    foo<int> test;
    return 0;
}

Je sais qu'il est bon de mettre tout cela dans un fichier d'en-tête, mais si nous instancier les modèles avec les mêmes paramètres dans plusieurs fichiers, puis nous avons eu de multiples mêmes définitions et le compilateur va supprimer tous (sauf un) pour éviter les erreurs. Comment puis-je utiliser extern template? Pouvons-nous l'utiliser uniquement pour les classes, ou pouvons-nous l'utiliser pour les fonctions de trop?

Aussi, la Figure 1 et la Figure 2 peut être étendu à une solution où les modèles sont dans un seul fichier d'en-tête . Dans ce cas, nous devons utiliser l' extern template mot-clé pour éviter les multiples d'un même instantations. Est-ce que pour des classes ou des fonctions trop?

235voto

Dani Points 13077

Vous devez uniquement utiliser extern modèle pour forcer le compilateur à ne pas instancier un modèle lorsque vous savez qu'il va être instancié ailleurs, il est utilisé pour réduire le temps de compilation et de réduire objet de la taille du fichier.
Par exemple:

// 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>();
}

Cela se traduira dans les fichiers d'objet suivants:

source1.o
    void something1()
    void ReallyBigFunction<int>()    // Compiled first time

source2.o
    void something2()
    void ReallyBigFunction<int>()    // Compiled second time

Si les deux fichiers sont liés un void ReallyBigFunction<int>() seront rejetées, entraîne un gaspillage de temps de compilation et de l'objet de la taille du fichier.
Pour ne pas gaspiller le temps de compilation et d'objets de la taille du fichier, il y a un mot-clé extern qui en fait le compilateur compile pas une fonction de modèle. vous devez utiliser cette si et seulement si vous savez est utilisé dans le même binaire quelque part d'autre.
Changer source2.cpp pour

// source2.cpp

#include "header.h"
extern template ReallyBigFunction<int>();
void something2()
{
    ReallyBigFunction<int>();
}

Voici les fichiers de l'objet:

source1.o
    void something1()
    void ReallyBigFunction<int>() // compiled just one time

source2.o
    void something2()
    // No ReallyBigFunction<int> here because of the extern

Lors de ces deux seront reliés ensemble, le deuxième objet fichier suffit d'utiliser le symbole de l'objet premier de fichier. Pas besoin de jeter et aucune perte de temps de compilation et de l'objet de la taille du fichier.
Cela ne devrait être utilisé au sein d'un projet, comme dans les moments où vous utilisez un modèle comme vector<int> plusieurs fois, vous devez utiliser extern dans un seul fichier source.
Ceci s'applique également aux classes et fonctionnent comme un seul et même modèle de fonctions membres.

61voto

sehe Points 123151

Wikipedia a la meilleure description

En C++03, le compilateur doit instancier un modèle à chaque fois qu'un modèle est entièrement spécifié rencontré dans une unité de traduction. Si le modèle est instancié avec les mêmes types de de nombreuses unités de traduction, ce qui peut augmenter considérablement le temps de compilation. Il n'y a aucun moyen de éviter cela en C++03, de sorte que C++11 introduit extern modèle déclarations, analogue à extern les déclarations de données.

C++03 a cette syntaxe de forcer le compilateur à instancier un modèle:

  template class std::vector<MyClass>;

C++11 fournit maintenant cette syntaxe:

  extern template class std::vector<MyClass>;

qui indique au compilateur de ne pas instancier le modèle dans cette unité de traduction.

L'avertissement: nonstandard extension used...

Microsoft VC++ utilisé pour avoir une non-standard version de cette fonctionnalité depuis quelques années déjà (en C++03). Le compilateur signale que, pour prévenir des problèmes de portabilité avec code à compiler sur différents compilateurs.

Regardez l'exemple dans la page liée , pour vérifier qu'il fonctionne à peu près de la même façon. Vous pouvez vous attendre le message pour aller avec les futures versions de MSVC, sauf bien sûr lors de l'utilisation d'autres non-standard compilateur extensions en même temps.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X