Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Déclaration explicite de template

4 réponses
Avatar
Mickaël Wolff
Bonjour la liste,

J'espère que vous passez (ou avez passé) de bonnes vacances.
En ces temps estivaux, j'ai écrit une application dans laquelle j'ai
définit des templates. L'un d'entre eux est :


// Fichier <engine.h>
template<typename StrNeedle, typename StrHaystack = StrNeedle>
class search_engine ;

La définition étant un peu plus loin.

Une partie des fonction est définie dans un fichier <engine-impl.h>,
qui est un fichier contenant les définition des plus grosses fonctions
que je ne souhaite pas rendre inline. Donc j'ai un fichier <engine.cpp>
dans lequel je force l'« instantiation » des templates :

#include "engine-impl.h"

template class search_engine <std::wstring> ;

Vu que les fonctions correspondant à ces instantiations de template
sont déjà disponible, j'aimerais le signaler dans le fichier d'en-tête
<engine.h>. C'est surtout pour prévenir les problèmes d'édition de lien
liés à une déclaration multiples des fonctions. Pour ce faire, j'ai
rajouté :

class search_engine <std::wstring> ;

Mais contrairement aux classes normales, cela entraîne des erreurs
sur l'instantiation explicite de mes template.

Y a-t-il une méthode plus propre permettant de prévenir que certains
templates sont instanciés ? (j'ai essayé avec typedef et extern, mais
rien n'y fait).

Je compile avec g++ 4.3.1 sous Debian GNU/Linux. L'erreur suivante
survient lorsque je tente de déclarer un template instancié :

explicit instantiation of ‘struct
warg::search_engine<std::basic_string<wchar_t, std::char_
traits<wchar_t>, std::allocator<wchar_t> >, std::basic_string<wchar_t,
std::char_traits<wchar_t>, std::allocator<wc
har_t> > >’ before definition of template

Merci :)
--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org

4 réponses

Avatar
Fabien LE LEZ
On Mon, 18 Aug 2008 22:20:05 +0200, Mickaël Wolff
:

C'est surtout pour prévenir les problèmes d'édition de lien
liés à une déclaration multiples des fonctions.



J'ai peur de ne pas tout suivre. Quels problèmes as-tu exactement ?
Peux-tu donner un code minimal (mais complet) qui illustre le
problème ?


class search_engine <std::wstring> ;
Mais contrairement aux classes normales, cela entraîne des erreurs
sur l'instantiation explicite de mes template.



Je ne saisis pas bien ce que tu veux faire, mais j'ai l'impression que
tu mélanges l'instanciation d'une classe template, et instanciation de
ses fonctions membres.

Prends l'exemple du code suivant :

#include <string>

template <class T> class C
{
public: void f() { T::foo(); }
};

class HasFoo
{
public: static void foo() {}
};

int main()
{
C <HasFoo> c_foo; // 1
c_foo.f(); // 2

C <std::string> c_string; // 3
// c_string.f(); // 4
}

En (1), la classe C<HasFoo> est instanciée.
En (2), la fonction C<HasFoo>::f() est instanciée.
En (3), la classe C<std::string> est instanciée.

En (4), la fonction C<std::string>::f() ne peut pas être instanciée,
car std::string::foo() n'existe pas. (J'ai mis le code en commentaire
car il est erronné.)
Avatar
Mickaël Wolff
Fabien LE LEZ a écrit :
J'ai peur de ne pas tout suivre. Quels problèmes as-tu exactement ?
Peux-tu donner un code minimal (mais complet) qui illustre le
problème ?



Je ne peux pas spécifier dans un en-tête qu'une instantiation de
template existe déjà.


Je ne saisis pas bien ce que tu veux faire, mais j'ai l'impression que
tu mélanges l'instanciation d'une classe template, et instanciation de
ses fonctions membres.



D'après mes essais, l'instantiation explicite de la template
instancie les fonctions membre de la classe template.


Prends l'exemple du code suivant :



[snip]

En (1), la classe C<HasFoo> est instanciée.
En (2), la fonction C<HasFoo>::f() est instanciée.
En (3), la classe C<std::string> est instanciée.



Effectivement, ça j'ai bien compris. C'est le principe de base de la
STL. J'ai écrit un petit exemple, que je mets en fin de message. Je fais
juste une parenthèse pour dire que ce que je présente ici fonctionne
très bien. Mon seul soucis, c'est que dans le fichier d'en-tête (tpl.h
dans l'exemple, et non tpl-impl.h), les templates instanciés ne sont pas
déclarés, et qu'il m'est impossible de faire un typedef sans avoir
d'erreurs.

== <main.cpp> ====== 8< ===== #include "tpl.h"

int main(int argc, char ** argv)
{
// pas d'instantiation, puisque déjà instancié
engine<std;;string> e("The street") ;
e.walk() ;
}

== <tpl.cpp> ====== 8< ===== #include "tpl-imp.h"

// On force l'instanciation du template en utilisant
// l'instanciation explicite :
template class engine<std::string> ;

== <tpl-impl.h> ====== 8< ===== #include "tpl.h"

template <typename T>
engine::engine()
{
}

template <typename T>
void engine::walk()
{
}

== <tpl.h> ====== 8< ===== template <typename T>
class engine
{
public:
engine() ;

void walk() ;
} /* class engine */ ;


--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Avatar
Jean-Marc Bourguet
Mickaël Wolff writes:

Fabien LE LEZ a écrit :
J'ai peur de ne pas tout suivre. Quels problèmes as-tu exactement ?
Peux-tu donner un code minimal (mais complet) qui illustre le problème ?



Je ne peux pas spécifier dans un en-tête qu'une instantiation de template
existe déjà.



extern template devrait resoudre ton probleme dans C++0X, si je l'ai bien
compris.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1987.htm

Il me semble me souvenir que gcc fournit cela comme extension depuis
longtemps, mais j'ai pas le temps de regarder.

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
James Kanze
On Aug 18, 10:20 pm, Mickaël Wolff wrote:
En ces temps estivaux, j'ai écrit une application dans laquelle j'ai
définit des templates. L'un d'entre eux est :



// Fichier <engine.h>
template<typename StrNeedle, typename StrHaystack = StrNeedle>
class search_engine ;



La définition étant un peu plus loin.



Une partie des fonction est définie dans un fichier <engine-impl.h>,
qui est un fichier contenant les définition des plus grosses fonctions
que je ne souhaite pas rendre inline. Donc j'ai un fichier <engine.cpp>
dans lequel je force l'« instantiation » des templates :



#include "engine-impl.h"



template class search_engine <std::wstring> ;



Vu que les fonctions correspondant à ces instantiations de template
sont déjà disponible, j'aimerais le signaler dans le fichier d'en-t ête
<engine.h>. C'est surtout pour prévenir les problèmes d'édition de lien
liés à une déclaration multiples des fonctions. Pour ce faire, j'ai
rajouté :



class search_engine <std::wstring> ;



Mais contrairement aux classes normales, cela entraîne des erreurs
sur l'instantiation explicite de mes template.



Y a-t-il une méthode plus propre permettant de prévenir que certai ns
templates sont instanciés ? (j'ai essayé avec typedef et extern, mais
rien n'y fait).



Je ne suis pas sûr ce que dit la norme à cet égard ; je crois
rien. Mais dans la practique, si la définition d'un tempate dont
le compilateur a besoin n'est pas disponible lors de la
compilation, le compilateur « suppose » qu'il a été instantié
ailleur.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34