OVH Cloud OVH Cloud

[débutant] StringConverter générique

6 réponses
Avatar
AG
Bonjour,

J'ai tenté ça :

#include <string>

template <class C> class Serialize
{
public:

typedef std::string CToString (C);

std::string operator() (std::string &id, C value, CToString F);
};

std::string Serialize<class C>::operator ()(std::string & id,C value,
CToString F)
{
return "[" + id + "] = " + F(value) + std::endl;
}

Mais ça ne compile pas. je ne comprends pas bien le message d'erreur :

serialize.cpp(4) : error C2511: '()' : overloaded member function 'class
std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> > (class std::basic_string<cha
r,struct std::char_traits<char>,class std::allocator<char> > &,class
C,class std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> > (__cdecl *)(class C))' not found in
'Serialize<class C>'

serialize.cpp(8) : error C2955: 'Serialize' : use of class template
requires template argument list
serialize.h(15) : see declaration of 'Serialize'
serialize.cpp(8) : error C2955: 'Serialize' : use of class template
requires template argument list
serialize.h(15) : see declaration of 'Serialize'

et notamment le __cdecl *

visiblement, il cherche la fonction F, mais ne la trouve pas.
Quelqu'un pourrait-t-il m'expliquer ?

Merci.

AG.

6 réponses

Avatar
Loïc Joly
AG wrote:

Bonjour,

J'ai tenté ça :

#include <string>

template <class C> class Serialize
{
public:

typedef std::string CToString (C);

std::string operator() (std::string &id, C value, CToString F);
};

std::string Serialize<class C>::operator ()(std::string & id,C value,
CToString F)
{
return "[" + id + "] = " + F(value) + std::endl;
}


Tu dois définir ta fonction ainsi :
template <class C>
std::string
Serialize<C>::operator ()(std::string & id,C value, CToString F)


Mais ça ne compile pas. je ne comprends pas bien le message d'erreur :
[...]


et notamment le __cdecl *


Dans un premier temps, tu peux l'oublier, c'est du genre soupe interne.
L'erreur C2955 était ici la plus explicite.

--
Loïc

Avatar
kanze
AG wrote:

J'ai tenté ça :

#include <string>

template <class C> class Serialize
{
public:

typedef std::string CToString (C);

std::string operator() (std::string &id, C value, CToString F);


Est-ce que le premier paramètre ne doit pas être const ?

Aussi, pourquoi cette fonction est-elle membre de la classe ?
Dans l'implémentation, elle ne semble rien utiliser de la
classe.

};


Il manque un « template< class C > » ici, pour que la fonction
suivante soit légal.

std::string Serialize<class C>::operator ()(std::string & id,C value,

CToString F)
{
return "[" + id + "] = " + F(value) + std::endl;


Je ne sais pas ce que ça veut dire d'ajouter une fonction
(std::endl) à une chaîne. De toute façon, étant donné que la
fonction est un template, le compilateur ne sait pas laquelle
prendre.

Peut-être simplement "n" ?

}



Mais ça ne compile pas. je ne comprends pas bien le message d'erreur
:


serialize.cpp(4) : error C2511: '()' : overloaded member function
'class

std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> > (class std::basic_string<cha
r,struct std::char_traits<char>,class std::allocator<char> > &,class
C,class std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> > (__cdecl *)(class C))' not found in
'Serialize<class C>'

serialize.cpp(8) : error C2955: 'Serialize' : use of class template
requires template argument list
serialize.h(15) : see declaration of 'Serialize'
serialize.cpp(8) : error C2955: 'Serialize' : use of class template
requires template argument list
serialize.h(15) : see declaration of 'Serialize'

et notamment le __cdecl *


Ça ne signifie rien (ou plutôt, ça signifie que tu, ou la
bibliothèque dont tu te sers, utilise des extensions Microsoft).

Pour la reste, j'ai l'impression que le compilateur n'arrive pas
à associer la définition de la fonction à sa déclaration dans la
classe.

visiblement, il cherche la fonction F, mais ne la trouve pas.


D'après le message d'erreur, ce n'est pas ça. Essaie en
remplaçant « class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> > » par
std::string dans le message d'erreur. Ce qu'il ne trouve pas,
c'est std::string ()(std::string&, class C, std::string
(*)(class C)) », c-à-d ton opérateur même.

Quelqu'un pourrait-t-il m'expliquer ?


Essaie déjà avec les corrections que j'ai proposé. Avec le
template en plus avant la définition de la fonction et la
substitution de 'n' pour std::endl, ça marche chez moi (Sun
CC 5.5 ou g++ 3.4.3). Mais je me poserais aussi des questions
vis-à-vis des const, voir même si la fonction doit être membre.

--
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

Avatar
AG
wrote:
AG wrote:


J'ai tenté ça :



#include <string>



template <class C> class Serialize
{
public:



typedef std::string CToString (C);



std::string operator() (std::string &id, C value, CToString F);



Est-ce que le premier paramètre ne doit pas être const ?
Pour tout t'avouer, j'ai décidé, dans mon processus d'apprentissage du

C++, de laisser de coté les histoires de "const" pour l'instant. Je
n'arrive pas à traiter tous les problèmes en même temps, et j'avais
l'impression que mettre le "const" de coté au début n'était pas
primordial. Mais peut être ai-je tord.


Aussi, pourquoi cette fonction est-elle membre de la classe ?
Dans l'implémentation, elle ne semble rien utiliser de la
classe.
C'est vrai. Il faudrait alors que je fasse une fonction template plutôt

qu'une classe ?


Il manque un « template< class C > » ici, pour que la fonction
suivante soit légal.
Oui, Loïc me l'a indiqué, j'ai compris maintenant.



std::string Serialize<class C>::operator ()(std::string & id,C value,



CToString F)
{
return "[" + id + "] = " + F(value) + std::endl;



Je ne sais pas ce que ça veut dire d'ajouter une fonction
(std::endl) à une chaîne. De toute façon, étant donné que la
fonction est un template, le compilateur ne sait pas laquelle
prendre.

Peut-être simplement "n" ?
oui, c'est ce à quoi je pensais. Je croyais que c'était la même chose,

mais en plus portable. Visiblement non.


Mais ça ne compile pas. je ne comprends pas bien le message d'erreur


:

serialize.cpp(4) : error C2511: '()' : overloaded member function


'class

std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> > (class std::basic_string<cha
r,struct std::char_traits<char>,class std::allocator<char> > &,class
C,class std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> > (__cdecl *)(class C))' not found in
'Serialize<class C>'



D'après le message d'erreur, ce n'est pas ça. Essaie en
remplaçant « class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> > » par
std::string dans le message d'erreur. Ce qu'il ne trouve pas,
c'est std::string ()(std::string&, class C, std::string
(*)(class C)) », c-à-d ton opérateur même.


C'est ce que j'avais fais, mais je tombe plutot sur :

std::string (std::string &,class C, std::string (*)(class C))

(à moins que je louche), il manque pas le "operator()" ou "()" ?


Essaie déjà avec les corrections que j'ai proposé. Avec le
template en plus avant la définition de la fonction et la
substitution de 'n' pour std::endl, ça marche chez moi (Sun
CC 5.5 ou g++ 3.4.3). Mais je me poserais aussi des questions
vis-à-vis des const, voir même si la fonction doit être membre.


Oui, j'essaye ça ce soir et je vous dis. L'idée de la classe c'est de
pouvoir fournir une fonction (l'opérateur ()) de formatage de n'importe
quel type (int, unsigned long, double, etc...) en string, avec un
identifiant spécial à chaque fois.

Merci à vous deux.

AG.


Avatar
AG
Alors voilà un copier coller de mon code :

#include <string>
#include <vector>

template <class C> class Serialize
{
public:

typedef std::string CToString(C);

std::string operator() (std::string & id,C value, CToString F);
};

template< class C > std::string Serialize<C>::operator() (std::string &
id,C value, CToString F)
{
return "[" + id + "] = " + F(value) + "n";
}


ça compile (j'ai pas essayé l'édition de liens) avec gcc 3.3.1 (cygming
special)

mais avec Visual C++ 6.0, ça me donne une erreur :

serialize.cpp(17) : error C2244: 'Serialize<C>::()' : unable to resolve
function overload

et le curseur se positionne sur l'accolade fermante de la définition de
la fonction Serialize<C>::operator()

J'ai vu ce genre d'erreur dans les archives :

http://groups.google.fr/groups?hl=fr&lr=&threadm†7108480.15250%40dejanews.com&rnum=3&prev=/groups%3Fq%3Derror%2BC2244%2Bunable%2Bto%2Bresolve%2Bfunction%2Boverload%26hl%3Dfr%26lr%3D%26selm%3D867108480.15250%2540dejanews.com%26rnum%3D3

donc j'ai bougé la définition de la fonction dans le corps de la classe,
et ça fonctionne :-(

pfff... C'est dur le C++.

AG.
Avatar
kanze
AG wrote:
wrote:
AG wrote:

J'ai tenté ça :

#include <string>

template <class C> class Serialize
{
public:

typedef std::string CToString (C);

std::string operator() (std::string &id, C value, CToString F);


Est-ce que le premier paramètre ne doit pas être const ?


Pour tout t'avouer, j'ai décidé, dans mon processus
d'apprentissage du C++, de laisser de coté les histoires de
"const" pour l'instant. Je n'arrive pas à traiter tous les
problèmes en même temps, et j'avais l'impression que mettre le
"const" de coté au début n'était pas primordial. Mais peut
être ai-je tord.


Le const n'est pas si difficile que ça. C'est vrai qu'il faut
traiter les choses dans l'ordre, mais je dirais qu'il vaut mieux
l'apprendre avant les templates, par exemple.

Aussi, pourquoi cette fonction est-elle membre de la classe
? Dans l'implémentation, elle ne semble rien utiliser de la
classe.


C'est vrai. Il faudrait alors que je fasse une fonction
template plutôt qu'une classe ?


Tout dépend de ce que tu veux faire, mais tel que c'est écrit
maintenant, je ne vois pas l'intérêt de la classe.

Note bien qu'il y a une déduction automatique des types pour les
fonctions templatées, qui les rendent souvent plus facile à
utiliser.

Il manque un « template< class C > » ici, pour que la
fonction suivante soit légal.


Oui, Loïc me l'a indiqué, j'ai compris maintenant.

std::string Serialize<class C>::operator ()(std::string & id,C
value,



CToString F)
{
return "[" + id + "] = " + F(value) + std::endl;


Je ne sais pas ce que ça veut dire d'ajouter une fonction
(std::endl) à une chaîne. De toute façon, étant donné que la
fonction est un template, le compilateur ne sait pas
laquelle prendre.

Peut-être simplement "n" ?


oui, c'est ce à quoi je pensais. Je croyais que c'était la
même chose, mais en plus portable. Visiblement non.


Pas du tout. std::endl dit de s'achever la sortie en cours.
C'est ce qu'on appelle un manipulateur, c-à-d une fonction qui
serait appelée au bon moment sur le flux. Et la sémantique de la
fonction, c'est bien d'ajouter un 'n' au flux, puis de faire un
flush.

C'est donc ce qu'il faut faire par défaut pour terminer une
ligne dans une sortie vers un flux. Mais c'est une action, non
une donnée, et c'est une action qui n'a de sens que sur un flux.

Mais ça ne compile pas. je ne comprends pas bien le message
d'erreur :

serialize.cpp(4) : error C2511: '()' : overloaded member
function 'class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> > (class
std::basic_string<cha r,struct std::char_traits<char>,class
std::allocator<char> > &,class C,class
std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> > (__cdecl *)(class C))' not found in
'Serialize<class C>'


D'après le message d'erreur, ce n'est pas ça. Essaie en
remplaçant « class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> > » par
std::string dans le message d'erreur. Ce qu'il ne trouve pas,
c'est std::string ()(std::string&, class C, std::string
(*)(class C)) », c-à-d ton opérateur même.


C'est ce que j'avais fais, mais je tombe plutot sur :

std::string (std::string &,class C, std::string (*)(class C))


Tout à fait.

(à moins que je louche), il manque pas le "operator()" ou "()" ?


Ce que tu as là, c'est la signature de la fonction, sans le nom.
À mon avis, le message aurait été plus clair avec le nom à sa
place, mais apparamment, le compiateur met le nom (« () »)
avant, suivi de la signature.

Essaie déjà avec les corrections que j'ai proposé. Avec le
template en plus avant la définition de la fonction et la
substitution de 'n' pour std::endl, ça marche chez moi (Sun
CC 5.5 ou g++ 3.4.3). Mais je me poserais aussi des
questions vis-à-vis des const, voir même si la fonction doit
être membre.


Oui, j'essaye ça ce soir et je vous dis. L'idée de la classe
c'est de pouvoir fournir une fonction (l'opérateur ()) de
formatage de n'importe quel type (int, unsigned long, double,
etc...) en string, avec un identifiant spécial à chaque fois.


Mais une fonction a aussi un opérateur (). Tout dépend de ce que
tu veux faire. Pour la sérialisation, je verais bien une classe,
qui containait la destination (un ofstream, par exemple). Mais
une classe non templatée, avec une fonction membre (ou
plusieurs) templatée. Donc, peut-être un operator<<, qui insère
directement dans le flux, avec une conversion en texte comme il
se fait classiquement, mais en insérant des séparateurs où il
faut (et une spécialisation explicite pour std::string et char
const*, de façon à mettre le chaîne en "..." s'il faut), les
identificateurs se trouvant dans un std::map. Mais tout dépend
de ce que tu veux faire.

--
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



Avatar
kanze
AG wrote:

[...]
mais avec Visual C++ 6.0, ça me donne une erreur :


Tu débutes ? Alors, fais une mise à jour.

Professionnellement, il y a encore beaucoup de projets qui se
servent de VC++ 6.0, pour diverses raisons, en général liées au
code existant. Mais c'est un compilateur bien vieux, et assez
faiblard en ce qui concerne les templates. Pour un nouveau
projet, ou pour apprendre, il n'y a pas de raison de ne pas
passer à une version plus récente. (Il y a même eu une version
gratuite -- je ne sais pas si c'est encore le cas.)

--
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