Bonjour tout le monde,
Je cherche une méthode afin d'exporter une version compilée de mes templates au sein d'une bibliothèque sans pour autant fournir le fichier du template.
Est-ce faisable?
Merci
Version imprimable
Bonjour tout le monde,
Je cherche une méthode afin d'exporter une version compilée de mes templates au sein d'une bibliothèque sans pour autant fournir le fichier du template.
Est-ce faisable?
Merci
Une version compilée de templates c++ ? Ça ne fait pas sens pour moi vu que les templates sont utilisés à la compilation :weird:
Ou ai-je mal compris la question ?
Oui, je me suis mal exprimé. En fait, j'ai un template représentant des images. Ces images peuvent être soient de type float soit de type entier par exemple. Je voulais éviter de donner l'implémentation de cette classe template en ne donnant juste leur "spécialisation" (en utilisant typedef par exemple).
Oui si comme j'ai compris, c'est le type de données qui est templatisé, tu dois pouvoir faire un typedef dans un header.
Code:
1
2
3
4
5
6
7
8
9
10
11
12 template<typename T> class mine { public: mine(T v):d(v){} private: T d; }; typedef mine<int> mineint; typedef mine<float> minefloat;
Tu peux passer par une astuce: la spécialisation de type incomplet:
La classe template n'est pas définie dans le cas général, et est spécialisée pour deux cas précis
L'en-tête contiendrait:
Code:
1
2
3
4
5
6
7
8
9
10
11
12 template <typename T> class Bidule; //surtout pas d'accolades template <> class Bidule<int> { // ce que tu veux }; template <typename T> class Bidule<float> { // ce que tu veux };
Merci pour vos réponses.
@SkyZoThreaD: le problème avec cette méthode, c'est que j'exporte le template ce que je souhaite.
@leternel: je ne souhaite pas vraiment spécialiser les templates, mais plutôt les définir.
Mon but est d'éviter d'inclure certains en-tête entraînant des dépendances indésirables.
Voici un exemple:
Je ne vois vraiment pas si c'est possible mais bon, peut-être qu'il existe une petite astuce sympa pour ce genre de problème.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 // Dans Image.hxx qui ne serait pas exporté #include <header_indesirable.hpp> template<typename T> class Image { public: Image(){} void method(); // Méthode qui utilise header_indesirable.hpp private: T m_data; }; template<typename T> void method() { // du code } // Dans ImageImpl.hpp qui serait exporté typedef Image<int> ImageInt; typedef Image<float> ImageFloat;
Donc c'est ce que tu souhaites ? :mouarf: Je vais considérer que tu ne le souhaites pas ;)
Je ne comprend toujours pas bien la question, mais il me semble que tu veux précompiler des templates non spécifiés et comme je l'ai écris avant il me semble que c'est impossible. Les templates sont utilisés à la compilation...
Effectivement, je ne le souhaite pas ^^
Effectivement, je souhaite précompiler mes templates pour les cas que j'ai spécifié (des images en int et en float). Après, j'ai une solution, recoder la classe sans utilisé de template mais bon c'est un peu lourd ^^
Ok tout est clair maintenant :mrgreen:
Donc je ne pense pas que ce soit possible mais attend la réponse d'un plus calé que moi. Le c++ est si tortueux... sait-on jamais...
C'est possible. ;)
Voici un exemple illustratif :
CartableCasse.h :
CartoucheCasse.h :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 #ifndef MODELE_PAS_DEFINI_DANS_ENTETE_CARTABLE_CASSE #define MODELE_PAS_DEFINI_DANS_ENTETE_CARTABLE_CASSE #include <iostream> class CartableCasse { public: void car() const { std::cout << "CartableCasse::car()\n"; } void table() const { std::cout << "CartableCasse::table()\n"; } void casse() const { std::cout << "CartableCasse::casse()\n"; } }; #endif
MonModele.h :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 #ifndef MODELE_PAS_DEFINI_DANS_ENTETE_CARTOUCHE_CASSE #define MODELE_PAS_DEFINI_DANS_ENTETE_CARTOUCHE_CASSE #include <iostream> class CartoucheCasse { public: void car() const { std::cout << "CartoucheCasse::car()\n"; } void touche() const { std::cout << "CartoucheCasse::touche()\n"; } void casse() const { std::cout << "CartoucheCasse::casse()\n"; } }; #endif
MonModele_impl.h :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 #ifndef MODELE_PAS_DEFINI_DANS_ENTETE_MON_MODELE #define MODELE_PAS_DEFINI_DANS_ENTETE_MON_MODELE template<class T> class MonModele { private: T m_data; public: void carcasse() const; void cartable() const; void cartouche() const; }; #endif
MonModeleCartableCasse.cpp :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 #ifndef MODELE_PAS_DEFINI_DANS_ENTETE_MON_MODELE_IMPL #define MODELE_PAS_DEFINI_DANS_ENTETE_MON_MODELE_IMPL #include "MonModele.h" template<class T> void MonModele<T>::carcasse() const { m_data.car(); m_data.casse(); } template<class T> void MonModele<T>::cartable() const { m_data.car(); m_data.table(); } template<class T> void MonModele<T>::cartouche() const { m_data.car(); m_data.touche(); } #endif
MonModeleCartoucheCasse.cpp :Code:
1
2
3
4
5
6 #include "CartableCasse.h" #include "MonModele_impl.h" // Instancier les fonctions qui compilent pour T = CartableCasse : template void MonModele<CartableCasse>::carcasse() const; template void MonModele<CartableCasse>::cartable() const;
main.cpp :Code:
1
2
3
4
5
6 #include "CartoucheCasse.h" #include "MonModele_impl.h" // Instancier les fonctions qui compilent pour T = CartoucheCasse : template void MonModele<CartoucheCasse>::carcasse() const; template void MonModele<CartoucheCasse>::cartouche() const;
Sortie :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include "MonModele.h" #include "CartableCasse.h" #include "CartoucheCasse.h" #include <iostream> int main() { MonModele<CartableCasse> foo; foo.carcasse(); foo.cartable(); std::cout << '\n'; MonModele<CartoucheCasse> bar; bar.carcasse(); bar.cartouche(); return 0; }
Code:
1
2
3
4
5
6
7
8
9 CartableCasse::car() CartableCasse::casse() CartableCasse::car() CartableCasse::table() CartoucheCasse::car() CartoucheCasse::casse() CartoucheCasse::car() CartoucheCasse::touche()
Bonjour,
En utilisant les extern template, et en forçant les instanciations on peut aussi le faire sur la classe entière
fichier .h
fichier .cppCode:
1
2
3
4
5
6
7
8
9
10
11
12 #ifndef DLLMASQUEE #define DLLIMP __declspec(dllimport) #else #define DLLIMP __declspec(dllexport) #endif template<class T> class DLLIMP Masquee { T x; public: Masquee(T const x) : x{ x } {} T action()const; };
On pourra alors utiliser les Masquee<> qui ont été instanciées dans la DLL.Code:
1
2
3
4
5
6
7
8
9 #define DLLMASQUEE #include "Masquee.h" template<class T> T Masquee<T>::action()const { return 2 * x; } template class Masquee<int>; // forcer l'instanciation des cas int et float template class Masquee<float>;
Je me rends compte que mon exemple précédent était inutilement compliqué.
J'ai créé un exemple un peu plus simple qui utilise aussi l'astuce que viens de donner dalfab :
Car.h :
Cartable.h :Code:
1
2
3
4
5
6
7
8
9
10
11
12 #ifndef MODELE_PAS_DEFINI_DANS_ENTETE_CAR #define MODELE_PAS_DEFINI_DANS_ENTETE_CAR #include <iostream> class Car { public: void car() const { std::cout << "Car::car()\n"; } }; #endif
DoubleAction_light.h :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13 #ifndef MODELE_PAS_DEFINI_DANS_ENTETE_CARTABLE #define MODELE_PAS_DEFINI_DANS_ENTETE_CARTABLE #include <iostream> class Cartable { public: void car() const { std::cout << "Cartable::car()\n"; } void table() const { std::cout << "Cartable::table()\n"; } }; #endif
DoubleAction.h :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 #ifndef MODELE_PAS_DEFINI_DANS_ENTETE_DOUBLE_ACTION_LIGHT #define MODELE_PAS_DEFINI_DANS_ENTETE_DOUBLE_ACTION_LIGHT #include <iostream> template<class T> class DoubleAction { private: T m_data; public: DoubleAction() { std::cout << "DoubleAction constructor\n"; } ~DoubleAction(); void doubleCar() const; void doubleTable() const; }; #endif
DoubleAction_Car_Cartable.cpp :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 #ifndef MODELE_PAS_DEFINI_DANS_ENTETE_DOUBLE_ACTION #define MODELE_PAS_DEFINI_DANS_ENTETE_DOUBLE_ACTION #include "DoubleAction_light.h" template<class T> DoubleAction<T>::~DoubleAction() { std::cout << "DoubleAction destructor\n"; } template<class T> void DoubleAction<T>::doubleCar() const { m_data.car(); m_data.car(); } template<class T> void DoubleAction<T>::doubleTable() const { m_data.table(); m_data.table(); } #endif
Main.cpp :Code:
1
2
3
4
5
6
7
8
9
10 #include "Car.h" #include "Cartable.h" #include "DoubleAction.h" // Instancier les fonctions qui compilent pour T = Car : template DoubleAction<Car>::~DoubleAction(); template void DoubleAction<Car>::doubleCar() const; // Instancier toute la classe pour T = Cartable : template class DoubleAction<Cartable>;
Sortie :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include "Car.h" #include "Cartable.h" #include "DoubleAction_light.h" #include <iostream> int main() { DoubleAction<Car> foo; foo.doubleCar(); std::cout << '\n'; DoubleAction<Cartable> bar; bar.doubleCar(); bar.doubleTable(); std::cout << '\n'; return 0; }
Code:
1
2
3
4
5
6
7
8
9
10
11
12 DoubleAction constructor Car::car() Car::car() DoubleAction constructor Cartable::car() Cartable::car() Cartable::table() Cartable::table() DoubleAction destructor DoubleAction destructor
Super!
Merci pour vos conseils!
Je viens de faire des tests et je vais utiliser la méthode de dalfab plutôt.
Voici mon petit exemple de test avec les fichiers CMake associés (j'ai testé sous Visual Studio 2010 et 2015).
Pièce jointe 218840