3 votes

classe de modèle et classe de modèle externe respective dans la même unité de traduction

Est-ce une utilisation correcte du modèle externe en C++11 ? (Se peut-il que le extern template class et respectifs template class est visible dans la même unité de traduction)

// example.hpp:
#pragma once
template< typename T >
class C {
    void f(T);
};
// question is about the next two lines
extern template class C< float >;
extern template class C< double >;
// example_def.hpp:
#include "example.hpp"
template< typename T >
void C< T >::f(T) {
    //... smth. practicable
}
// example.cpp:
#include "example_def.hpp"
template class C< float >;
template class C< double >;
// other.hpp:
#pragma once
void g();
// other.cpp:
#include "other.hpp"
#include "example.hpp"
// maybe those two lines should be here instead?
void g() {
    C< float >();
    C< double >();
}
// main.cpp:
#include "example.hpp"
#include "other.hpp"
// ...and here?
int main() {
    C< float >();
    C< double >();
    g();
    return 0;
}

4voto

jogojapan Points 26661

Oui, à la fois un extern template class (appelée instanciation explicite déclaration par la norme) et un template class (appelée instanciation explicite définition par la norme) peuvent se trouver dans la même unité de traduction, si la définition (sans extern ) suit la déclaration (avec extern ):

(§14.7.2/11) Si une entité fait l'objet à la fois d'une déclaration d'instanciation explicite et d'une dénition d'instanciation explicite dans la même unité de traduction, la dénition doit suivre la déclaration. Une entité qui fait l'objet d'une déclaration d'instanciation explicite et qui est également utilisée d'une manière qui causerait autrement une instanciation implicite (14.7.1) dans l'unité de traduction doit faire l'objet d'une dénition d'instanciation explicite quelque part dans le programme ; sinon le programme est mal formé, aucun diagnostic n'est requis. [Note : Cette règle s'applique aux fonctions en ligne même si une déclaration d'instanciation explicite d'une telle entité n'a aucun autre effet normatif. Cette règle est nécessaire pour garantir que si l'adresse d'une fonction inline est prise dans une unité de traduction dans laquelle l'implémentation a choisi de supprimer le corps hors ligne, une autre unité de traduction fournira le corps. - note de fin ] Une déclaration d'instanciation explicite ne doit pas nommer une spécialisation d'un modèle avec un lien interne.

(C'est moi qui souligne). Les termes déclaration d'instanciation explicite y définition explicite de l'instanciation sont définis ici :

(§14.7.2/2) La syntaxe de l'instanciation explicite est :

explicite-instanciation :
extern opt template déclaration

Il existe deux formes d'instanciation explicite : une dénition d'instanciation explicite et une déclaration d'instanciation explicite. Une déclaration d'instanciation explicite commence par le mot-clé extern.


En l'effet de ces instanciations explicites est le suivant :

  1. La déclaration d'instanciation explicite (avec extern ) empêche toute implicite pour prendre effet (sauf pour les fonctions en ligne et les modèles de classe). spécialisations , §14.7.2/10).

  2. La définition explicite de l'instanciation (sans extern ) provoque l'instanciation peu importe ce qui se passe c'est-à-dire qu'elle remplace la déclaration d'instanciation explicite (ceci découle également de la §14.7.2/10).


Commentaires généraux
Le fait que vos déclarations d'instanciation explicites se trouvent dans le fichier d'en-tête qui définit le modèle implique que quelqu'un qui inclut les fichiers d'en-tête afin d'utiliser le modèle devra également ajouter une instanciation explicite. définition ou, alternativement, a besoin d'un lien vers le code d'une autre entreprise. .cpp qui comprend une telle définition explicite de l'instanciation.

Cela peut prêter à confusion et ce n'est probablement pas une très bonne idée si vous vous attendez à ce que de nombreux utilisateurs différents instancient le modèle pour de nombreux types différents. Mais cela peut être judicieux si le nombre d'instanciations pour des types distincts est faible et que vous pouvez toutes les anticiper. Bien sûr, vous devez vous assurer qu'il existe un (ou plusieurs) .cpp qui incluent une instanciation explicite. définitions pour toutes les instanciations requises, et que le fichier objet correspondant est lié au projet au moment de la construction.

3voto

Dietmar Kühl Points 70604

L'idée de base de extern est de prendre en charge l'instanciation explicite des instanciations couramment utilisées tout en prenant également en charge les instanciations implicites pour les paramètres moins couramment utilisés. Par exemple, std::basic_string<char> pourrait être explicitement instancié mais std::basic_string<signed char> pourrait être laissée pour une instanciation implicite (les exemples actuels de motivation étaient les IOStreams qui prennent un temps considérable pour être instanciés mais seulement deux instanciations sont réellement utilisées).

Pour permettre une instanciation implicite, la définition des modèles utilisés doit être visible dans chaque unité de traduction où le modèle est utilisé. Si la définition du modèle est visible, le compilateur suppose par défaut qu'il doit fournir une instanciation implicite. L'utilisation d'un extern La déclaration du modèle indique au compilateur que l'instanciation spécifique du modèle sera fournie par une unité de traduction.

Bien que votre cas fonctionne, il n'est même pas nécessaire de déclarer la extern des modèles : Lorsque le compilateur utilise une instanciation et ne trouve pas sa définition, il suppose que l'instanciation se trouve dans une unité de traduction.

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