C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Template et spécialisation partiel d'une méthode...

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French)
View previous topic :: View next topic  
Author Message
Etienne
Guest





PostPosted: Tue May 09, 2006 2:22 pm    Post subject: Template et spécialisation partiel d'une méthode... Reply with quote



Bonjour,

Je vous montre ce que j'aurais aimé faire :

#include <iostream>
#include <string>

using namespace std;

template <class T, bool b>
class Toto
{
public:
Toto(const T& t) : _t (t)
{
}

void tata(void);

private:
T _t;
};

template <class T, bool b>
void Toto<T, false>::tata(void)
{
cout << "void Toto<T, false>::tata(void)" << endl;
}

template <class T, bool b>
void Toto<T, true>::tata(void)
{
cout << "void Toto<T, true>::tata(void)" << endl;
}

int main(void)
{
Toto<int, true> t1 (5);
Toto<int, false> t2 (6);

t1.tata();
t2.tata();

return 0;
}

Mais g++ n'aime pas mon code :
$ g++ t.cc
t.cc:22: error: no `void Toto<T, false>::tata()' member function
declared in
class `Toto<T, false>'
t.cc:22: error: template definition of non-template `void Toto<T,
false>::tata()'
t.cc:28: error: no `void Toto<T, true>::tata()' member function
declared in
class `Toto<T, true>'
t.cc:28: error: template definition of non-template `void Toto<T,
true>::tata()'

Pour résoudre ce problème j'ai du utilisé la spécialisation partiel
:
#include <iostream>
#include <string>

using namespace std;

template <class T, bool b>
class Toto
{
public:
Toto(const T& t) : _t (t)
{
}

void tata(void);

private:
T _t;
};

template <class T>
class Toto<T, true>
{
public:
Toto(const T& t) : _t (t)
{
}

void tata(void);

private:
T _t;
};

template <class T, bool b>
void Toto<T, b>::tata(void)
{
cout << "void Toto<T, false>::tata(void)" << endl;
}

template <class T>
void Toto<T, true>::tata(void)
{
cout << "void Toto<T, true>::tata(void)" << endl;
}

int main(void)
{
Toto<int, true> t1 (5);
Toto<int, false> t2 (6);

t1.tata();
t2.tata();

return 0;
}


Cela compile... mais je n'aime pas trop car il y a redondance de code.
Pour eviter cette duplication de code j'ai utilisé les macro :

#include <iostream>
#include <string>

using namespace std;

# define BODY\
{ \
public: \
Toto(const T& t) : _t (t) \
{ \
} \
\
void tata(void); \
\
private: \
T _t; \
}


template <class T, bool b> class Toto BODY;
template <class T> class Toto<T, true> BODY;

#undef BODY

template <class T, bool b>
void Toto<T, b>::tata(void)
{
cout << "void Toto<T, false>::tata(void)" << endl;
}

template <class T>
void Toto<T, true>::tata(void)
{
cout << "void Toto<T, true>::tata(void)" << endl;
}

int main(void)
{
Toto<int, true> t1 (5);
Toto<int, false> t2 (6);

t1.tata();
t2.tata();

return 0;
}

D'ou ma question : existe t-il une solution a mon probleme sans
duplication de code et sans macro ?

Etienne
Back to top
kanze
Guest





PostPosted: Wed May 10, 2006 7:21 am    Post subject: Re: Template et spécialisation partiel d'une méthode... Reply with quote



Etienne wrote:

Quote:
Je vous montre ce que j'aurais aimé faire :

#include <iostream
#include <string

using namespace std;

template <class T, bool b
class Toto
{
public:
Toto(const T& t) : _t (t)
{
}

void tata(void);

private:
T _t;
};

template <class T, bool b
void Toto<T, false>::tata(void)
{
cout << "void Toto<T, false>::tata(void)" << endl;
}

template <class T, bool b
void Toto<T, true>::tata(void)
{
cout << "void Toto<T, true>::tata(void)" << endl;
}

int main(void)
{
Toto<int, true> t1 (5);
Toto<int, false> t2 (6);

t1.tata();
t2.tata();

return 0;
}

Mais g++ n'aime pas mon code :
$ g++ t.cc
t.cc:22: error: no `void Toto<T, false>::tata()' member function
declared in
class `Toto<T, false>'
t.cc:22: error: template definition of non-template `void Toto<T,
false>::tata()'
t.cc:28: error: no `void Toto<T, true>::tata()' member function
declared in
class `Toto<T, true>'
t.cc:28: error: template definition of non-template `void Toto<T,
true>::tata()'

Pour résoudre ce problème j'ai du utilisé la spécialisation
partiel :

C'est en fait ce que tu veux, non ? Seulement, tu le veux sur la
fonction, et non sur la classe. Or, si j'ai bien compris, pour
les fonctions, on n'a pas de spécialisation partielle ; on
exploite plutôt la résolution du surcharge. Quelque chose du
genre :

template< bool b >
struct Discriminator {} ;

//...

template <class T, bool b>
class Toto
{
public:
void tata()
{
doTata( Discriminator< b >() ) ;
}
private:
void doTata( Discriminator< true > ) ;
void doTata( Discriminator< false > ) ;
} ;

template <class T, bool b>
void Toto<T, b>::doTata(Discriminator< false >)
{
cout << "void Toto<T, false>::tata(void)" << endl;
}

template <class T, bool b>
void Toto<T, b>::doTata(Discriminator< true>)
{
cout << "void Toto<T, true>::tata(void)" << endl;
}

Sinon, dans des cas aussi simple qu'ici, Tu peux mettre le code
dans le discriminateur même, et appeler :
Discriminator< b >::tata() ;
ou
Discriminator< b >().tata() ;
dans Toto<>::tata().

--
James Kanze GABI Software
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
Back to top
Etienne
Guest





PostPosted: Wed May 10, 2006 4:22 pm    Post subject: Re: Template et spécialisation partiel d'une méthode... Reply with quote



Merci

Etienne
Back to top
gbaudin
Guest





PostPosted: Thu May 11, 2006 10:22 am    Post subject: Re: Template et spécialisation partiel d'une méthode... Reply with quote

Quote:
"kanze" <kanze@gabi-soft.fr> a écrit dans le message de news:
1147245490.749188.300020 (AT) v46g2000cwv (DOT) googlegroups.com...
Etienne wrote:

Je vous montre ce que j'aurais aimé faire :

#include <iostream
#include <string

using namespace std;

template <class T, bool b
class Toto
{
public:
Toto(const T& t) : _t (t)
{
}

void tata(void);

private:
T _t;
};

template <class T, bool b
void Toto<T, false>::tata(void)
{
cout << "void Toto<T, false>::tata(void)" << endl;
}

template <class T, bool b
void Toto<T, true>::tata(void)
{
cout << "void Toto<T, true>::tata(void)" << endl;
}

int main(void)
{
Toto<int, true> t1 (5);
Toto<int, false> t2 (6);

t1.tata();
t2.tata();

return 0;
}

Mais g++ n'aime pas mon code :
$ g++ t.cc
t.cc:22: error: no `void Toto<T, false>::tata()' member function
declared in
class `Toto<T, false>'
t.cc:22: error: template definition of non-template `void Toto<T,
false>::tata()'
t.cc:28: error: no `void Toto<T, true>::tata()' member function
declared in
class `Toto<T, true>'
t.cc:28: error: template definition of non-template `void Toto<T,
true>::tata()'

Pour résoudre ce problème j'ai du utilisé la spécialisation
partiel :

C'est en fait ce que tu veux, non ? Seulement, tu le veux sur la
fonction, et non sur la classe. Or, si j'ai bien compris, pour
les fonctions, on n'a pas de spécialisation partielle ; on
exploite plutôt la résolution du surcharge. Quelque chose du
genre :

template< bool b
struct Discriminator {} ;

//...

template <class T, bool b
class Toto
{
public:
void tata()
{
doTata( Discriminator< b >() ) ;
}
private:
void doTata( Discriminator< true > ) ;
void doTata( Discriminator< false > ) ;
} ;

template <class T, bool b
void Toto<T, b>::doTata(Discriminator< false >)
{
cout << "void Toto<T, false>::tata(void)" << endl;
}

template <class T, bool b
void Toto<T, b>::doTata(Discriminator< true>)
{
cout << "void Toto<T, true>::tata(void)" << endl;
}

Sinon, dans des cas aussi simple qu'ici, Tu peux mettre le code
dans le discriminateur même, et appeler :
Discriminator< b >::tata() ;
ou
Discriminator< b >().tata() ;
dans Toto<>::tata().

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung


Bonjour,
j'ai a peu pret une question similaire sauf que c'est sur la specialisation
d'une fonction membre d'une classe.
je ne sais pas si on peut faire ce genre de chose :
( j'utilise VC++ 6 )


dans un .h
class A
{
A();
~A()

void methode();

template < long T>
void autre_methode( ... );
};


donc dans le cpp

A::A()
{
}

A::~A()
{
}

void A::methode()
{
....
}

template <long T>
void A::autre_methode( ... )
{
....
} // Ceci est accepté par le
compilateur, mais je n'ai pas teste son fonctionnement ...

// si j'en veux une specialisation, comment je dois la declarer ?

template<>
void A::autre_methode<SPECIALISATION>( ... ) // fatal error
C1001: INTERNAL COMPILER ERROR
{
...
}

ou

template <>
void A<SPECIALISATION>::autre_methode( ... ) // syntax error :
missing ';' before '<'
{
...
}

Est ce que c'est faisable ???
merci.













9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Back to top
James Kanze
Guest





PostPosted: Sat May 13, 2006 9:21 am    Post subject: Re: Template et spécialisation partiel d' une méthode... Reply with quote

gbaudin wrote:
Quote:
"kanze" <kanze@gabi-soft.fr> a écrit dans le message de news:

[...]
Quote:
j'ai a peu pret une question similaire sauf que c'est sur la
specialisation d'une fonction membre d'une classe.

C'était l'exemple même. Il voulait en fait une spécialisation partielle
d'une fonction. Ça n'existe pas : c'est la spécialisation
partielle pour les classes, et le surcharge pour les fonctions.

Quote:
je ne sais pas si on peut faire ce genre de chose : (
j'utilise VC++ 6 )

dans un .h
class A
{
A();
~A()

void methode();

template < long T
void autre_methode( ... );
};

donc dans le cpp

A::A()
{
}

A::~A()
{
}

void A::methode()
{
...
}

template <long T
void A::autre_methode( ... )
{
....
} // Ceci est accepté par le
compilateur, mais je n'ai pas teste son fonctionnement ...

// si j'en veux une specialisation, comment je dois la declarer ?

template
void A::autre_methode<SPECIALISATION>( ... ) // fatal error
C1001: INTERNAL COMPILER ERROR
{
...
}

A priori, c'est correct. (Et le compilateur t'as dit qu'il y a
une erreur chez lui, non dans ton code.) Dans le cas d'une
fonction libre, en tout cas, il y a même un exemple à peu près
identique dans la norme :
template<> void sort<char*>(Array<char*>& v) { /*...*/ }
G++ accepte aussi la même chose quand la fonction est un membre.

Note que si le type figure parmi les paramètres, tu peux aussi
écrire simplement :
template<>
void A::autre_methode( ... ) { ... }
avec le paramètre explicité.

Quote:
ou

template
void A<SPECIALISATION>::autre_methode( ... ) // syntax error :
missing ';' before '<'
{
...
}

Là, c'est clair. Tu as démandé une spécialisation d'une fonction
non-templatéee dans une classe templatée. Ou plutôt... Du fait
que A n'est pas un template, le '<' qui en suit le nom signifie
l'opérateur « inférieur à ». Ce qui n'est pas légal dans ce
contexte.

Quote:
Est ce que c'est faisable ???

Le code suivant marche avec g++. Je dirais qu'il y a une erreur
dans ton compilateur. (En général, si tu vois le message
« internal compiler error », ou quelque chose du genre, tu peux
partir du principe qu'il y a une erreur dans le compilateur.
Peut-être aussi dans ton code aussi, mais sûrement dans le
compilateur.)

#include <iostream>
#include <ostream>

struct A
{
template< typename T >
void f()
{
std::cout << "A::f() générique" << std::endl ;
}
template< typename T >
void g( T const& )
{
std::cout << "A::g() générique" << std::endl ;
}
} ;

template<>
void A::f< int >()
{
std::cout << "A::f() spécialisée" << std::endl ;
}

template<>
void A::g( int const& )
{
std::cout << "A::g() spécialisée" << std::endl ;
}

int
main()
{
A a ;
a.f< double >() ;
a.f< int >() ;
a.g( 1.3 ) ;
a.g( 2 ) ;
return 0 ;
}

Faute d'autre chose, pour avancer, donne un paramètre bidon
(avec une valeur par défaut) à la fonction, et utiliser le
format qui m'a servi pour g(), ci-dessus, pour la
spécialisation. Avec un peu de chance, tu contourneras l'erreur
du compilateur.

--
James Kanze kanze.james (AT) neuf (DOT) fr
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
Back to top
gbaudin
Guest





PostPosted: Mon May 15, 2006 9:22 am    Post subject: Re: Template et spécialisation partiel d'une méthode... Reply with quote

"James Kanze" <kanze.james (AT) neuf (DOT) fr> a écrit dans le message de news:
e447if$poh$1 (AT) emma (DOT) aioe.org...
Quote:
gbaudin wrote:
"kanze" <kanze@gabi-soft.fr> a écrit dans le message de news:

[...]
j'ai a peu pret une question similaire sauf que c'est sur la
specialisation d'une fonction membre d'une classe.

C'était l'exemple même. Il voulait en fait une spécialisation partielle
d'une fonction. Ça n'existe pas : c'est la spécialisation
partielle pour les classes, et le surcharge pour les fonctions.

je ne sais pas si on peut faire ce genre de chose : (
j'utilise VC++ 6 )

dans un .h
class A
{
A();
~A()

void methode();

template < long T
void autre_methode( ... );
};

donc dans le cpp

A::A()
{
}

A::~A()
{
}

void A::methode()
{
...
}

template <long T
void A::autre_methode( ... )
{
....
} // Ceci est accepté par le
compilateur, mais je n'ai pas teste son fonctionnement ...

// si j'en veux une specialisation, comment je dois la declarer ?

template
void A::autre_methode<SPECIALISATION>( ... ) // fatal error
C1001: INTERNAL COMPILER ERROR
{
...
}

A priori, c'est correct. (Et le compilateur t'as dit qu'il y a
une erreur chez lui, non dans ton code.) Dans le cas d'une
fonction libre, en tout cas, il y a même un exemple à peu près
identique dans la norme :
template<> void sort<char*>(Array<char*>& v) { /*...*/ }
G++ accepte aussi la même chose quand la fonction est un membre.

Note que si le type figure parmi les paramètres, tu peux aussi
écrire simplement :
template
void A::autre_methode( ... ) { ... }
avec le paramètre explicité.

ou

template
void A<SPECIALISATION>::autre_methode( ... ) // syntax error :
missing ';' before '<'
{
...
}

Là, c'est clair. Tu as démandé une spécialisation d'une fonction
non-templatéee dans une classe templatée. Ou plutôt... Du fait
que A n'est pas un template, le '<' qui en suit le nom signifie
l'opérateur « inférieur à ». Ce qui n'est pas légal dans ce
contexte.

Est ce que c'est faisable ???

Le code suivant marche avec g++. Je dirais qu'il y a une erreur
dans ton compilateur. (En général, si tu vois le message
« internal compiler error », ou quelque chose du genre, tu peux
partir du principe qu'il y a une erreur dans le compilateur.
Peut-être aussi dans ton code aussi, mais sûrement dans le
compilateur.)

#include <iostream
#include <ostream

struct A
{
template< typename T
void f()
{
std::cout << "A::f() générique" << std::endl ;
}
template< typename T
void g( T const& )
{
std::cout << "A::g() générique" << std::endl ;
}
} ;

template
void A::f< int >()
{
std::cout << "A::f() spécialisée" << std::endl ;
}

template
void A::g( int const& )
{
std::cout << "A::g() spécialisée" << std::endl ;
}

int
main()
{
A a ;
a.f< double >() ;
a.f< int >() ;
a.g( 1.3 ) ;
a.g( 2 ) ;
return 0 ;
}

Faute d'autre chose, pour avancer, donne un paramètre bidon
(avec une valeur par défaut) à la fonction, et utiliser le
format qui m'a servi pour g(), ci-dessus, pour la
spécialisation. Avec un peu de chance, tu contourneras l'erreur
du compilateur.

--
James Kanze kanze.james (AT) neuf (DOT) fr
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


----- Original Message -----
From: "James Kanze" <kanze.james (AT) neuf (DOT) fr>
Newsgroups: fr.comp.lang.c++
Sent: Saturday, May 13, 2006 11:12 AM
Subject: Re: Template et spécialisation partiel d'une méthode...


Quote:
gbaudin wrote:
"kanze" <kanze@gabi-soft.fr> a écrit dans le message de news:

[...]
j'ai a peu pret une question similaire sauf que c'est sur la
specialisation d'une fonction membre d'une classe.

C'était l'exemple même. Il voulait en fait une spécialisation partielle
d'une fonction. Ça n'existe pas : c'est la spécialisation
partielle pour les classes, et le surcharge pour les fonctions.

je ne sais pas si on peut faire ce genre de chose : (
j'utilise VC++ 6 )

dans un .h
class A
{
A();
~A()

void methode();

template < long T
void autre_methode( ... );
};

donc dans le cpp

A::A()
{
}

A::~A()
{
}

void A::methode()
{
...
}

template <long T
void A::autre_methode( ... )
{
....
} // Ceci est accepté par le
compilateur, mais je n'ai pas teste son fonctionnement ...

// si j'en veux une specialisation, comment je dois la declarer ?

template
void A::autre_methode<SPECIALISATION>( ... ) // fatal error
C1001: INTERNAL COMPILER ERROR
{
...
}

A priori, c'est correct. (Et le compilateur t'as dit qu'il y a
une erreur chez lui, non dans ton code.) Dans le cas d'une
fonction libre, en tout cas, il y a même un exemple à peu près
identique dans la norme :
template<> void sort<char*>(Array<char*>& v) { /*...*/ }
G++ accepte aussi la même chose quand la fonction est un membre.

Note que si le type figure parmi les paramètres, tu peux aussi
écrire simplement :
template
void A::autre_methode( ... ) { ... }
avec le paramètre explicité.

ou

template
void A<SPECIALISATION>::autre_methode( ... ) // syntax error :
missing ';' before '<'
{
...
}

Là, c'est clair. Tu as démandé une spécialisation d'une fonction
non-templatéee dans une classe templatée. Ou plutôt... Du fait
que A n'est pas un template, le '<' qui en suit le nom signifie
l'opérateur « inférieur à ». Ce qui n'est pas légal dans ce
contexte.

Est ce que c'est faisable ???

Le code suivant marche avec g++. Je dirais qu'il y a une erreur
dans ton compilateur. (En général, si tu vois le message
« internal compiler error », ou quelque chose du genre, tu peux
partir du principe qu'il y a une erreur dans le compilateur.
Peut-être aussi dans ton code aussi, mais sûrement dans le
compilateur.)

#include <iostream
#include <ostream

struct A
{
template< typename T
void f()
{
std::cout << "A::f() générique" << std::endl ;
}
template< typename T
void g( T const& )
{
std::cout << "A::g() générique" << std::endl ;
}
} ;

template
void A::f< int >()
{
std::cout << "A::f() spécialisée" << std::endl ;
}

template
void A::g( int const& )
{
std::cout << "A::g() spécialisée" << std::endl ;
}

int
main()
{
A a ;
a.f< double >() ;
a.f< int >() ;
a.g( 1.3 ) ;
a.g( 2 ) ;
return 0 ;
}

Faute d'autre chose, pour avancer, donne un paramètre bidon
(avec une valeur par défaut) à la fonction, et utiliser le
format qui m'a servi pour g(), ci-dessus, pour la
spécialisation. Avec un peu de chance, tu contourneras l'erreur
du compilateur.

--
James Kanze kanze.james (AT) neuf (DOT) fr
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

effectivement, j'ai compilé et debuggé cet exemple avec g++ ...

sous VC++ 6 ca me donne le resultat que j'ai deja affiche plus haut :
Compiling...
main.cpp
c:\test\test\main.cpp(21) : fatal error C1001: INTERNAL COMPILER ERROR
(compiler file 'msc1.cpp', line 1794)
Please choose the Technical Support command on the Visual C++
Help menu, or open the Technical Support help file for more
information
Error executing cl.exe.

Test.exe - 1 error(s), 0 warning(s)

Avec VC++ 7, au moins il n'y a pas d'erreur du compilateur, mais il refuse
la surcharge
------ Rebuild All started: Project: Test, Configuration: Debug Win32 ------
Deleting intermediate files and output files for project 'Test',
configuration 'Debug|Win32'.
Compiling...
main.cpp
c:\test\Test\main.cpp(22) : error C2511: 'void A::f(void)' : overloaded
member function not found in 'A'
c:\test\Test\main.cpp(6) : see declaration of 'A'
c:\test\Test\main.cpp(2Cool : error C2511: 'void A::g(const int &)' :
overloaded member function not found in 'A'
c:\test\Test\main.cpp(6) : see declaration of 'A'
Build Time 0:00
Build log was saved at "file://c:\test\Test\Debug\BuildLog.htm"
Test - 2 error(s), 0 warning(s)


finalement avec VC++ 7.1 ( .Net 2003 ), ca compile et ca marche ... du coup
je n'ai pas testé avec VC++ 2005 mais a priori ca devrait fonctionner
egalement ...

voila si ces resultats interessent quelques personnes sur ces compilos ...

c'est quand même bien dommage qu'il n'y a pas de correctif sur les anciennes
versions ...

En fait je voulais utiliser ce type de syntaxe pour ne pas gerer d'enormes
switch dans le code ( a tort ou a raison ? ) mais utiliser une fonction
generale qui retourne une exception et des specialisations pour traiter les
cas particuliers ... Bon bein syntaxe "switch" power on en attendant Smile)

merci pour l'exemple car je doutais quand même que la syntaxe soit valide !
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.