J'ai besoin d'aide pour creer une fonction de type OutputDebugString
qui envoit un message de debuggage mais qui soit aussi facile a
utiliser que printf c'est a dire que je puisse l'utiliser de la sorte
la problématique, d'accès concurrentiel notamment, sera (quasiment) exactement la même pour coder le ostream& << (ostream&, Object&); (quasiment car le problème de la chaine retournée n'existe que pour l'appel à une fonction).
A 1h00 du matin et rapidement, je n'ai pas trouvé les mêmes problèmes dans ces deux approches.
J'imaginais quelque chose comme ça pour toString() : const char* object::toString() const { ... return quelquechose; }
oui, quelque chose cela, où "..." n'est pas char* quelquechose = new char[aLength]; sprintf(quelquechose, "<format>", members);
ni string quelquechose; quelquechose << members; (~quelquechose sera appelé avant le <<(const char*))
et là je ne vois pas trop de solution simple notamment pour la concurence sur un hypothétique buffer static (un peu à la "C" je dirais)
pour éviter la ""complexité"" d'une string interne (et/ou par étourderie) on pourrait se contenter d'un buffer global static, ce serait là une erreur en effet.
un tel buffer (unique) fournirait des contenus invalides en cas d'accès concurrentiel à 'la' méthode toString par différentes instances; je pensais également à des accès concurrentiels sur la même instance (le même object dumpé par plusieurs threads en même temps), là toutes les variantes listées ici échouent.
alors qu'avec un std::string object::toString() const { // ou asString(), j'hésite toujours. string tmp; // ... return tmp; }
c'est une option possible, elle évite une donnée membre String, et limite la problématique des accès concurrentiels au seul temps du remplissage de 'tmp'.
pour ma part, j'hésiterai un peu en faveur de la première façon car "std::string" n'est pas (pour moi et même si pour moi seul) un type standard, comme l'est un const char*; utiliser un string en interne à ma méthode est ma toutouille et me va, forcer l'utilisateur externe à connaitre ce type, ne me convient pas.
puis, pour faciliter une utilisation en mode flux : ostream& operator << ( ostream& os, const object& o ) { return os << o.toString(); }
qui permet d'utiliser directement: "ostream << instance;" sans coder un opérateur explicite.
Sylvain.
David wrote on 25/11/2006 00:55:
la problématique, d'accès concurrentiel notamment, sera (quasiment)
exactement la même pour coder le ostream& << (ostream&, Object&);
(quasiment car le problème de la chaine retournée n'existe que pour
l'appel à une fonction).
A 1h00 du matin et rapidement, je n'ai pas trouvé les mêmes problèmes
dans ces deux approches.
J'imaginais quelque chose comme ça pour toString() :
const char* object::toString() const {
...
return quelquechose;
}
oui, quelque chose cela, où "..." n'est pas
char* quelquechose = new char[aLength];
sprintf(quelquechose, "<format>", members);
ni
string quelquechose;
quelquechose << members;
(~quelquechose sera appelé avant le <<(const char*))
et là je ne vois pas trop de solution simple notamment pour la
concurence sur un hypothétique buffer static (un peu à la "C" je dirais)
pour éviter la ""complexité"" d'une string interne (et/ou par
étourderie) on pourrait se contenter d'un buffer global static, ce
serait là une erreur en effet.
un tel buffer (unique) fournirait des contenus invalides en cas d'accès
concurrentiel à 'la' méthode toString par différentes instances; je
pensais également à des accès concurrentiels sur la même instance (le
même object dumpé par plusieurs threads en même temps), là toutes les
variantes listées ici échouent.
alors qu'avec un
std::string object::toString() const {
// ou asString(), j'hésite toujours.
string tmp;
// ...
return tmp;
}
c'est une option possible, elle évite une donnée membre String, et
limite la problématique des accès concurrentiels au seul temps du
remplissage de 'tmp'.
pour ma part, j'hésiterai un peu en faveur de la première façon car
"std::string" n'est pas (pour moi et même si pour moi seul) un type
standard, comme l'est un const char*; utiliser un string en interne à ma
méthode est ma toutouille et me va, forcer l'utilisateur externe à
connaitre ce type, ne me convient pas.
puis, pour faciliter une utilisation en mode flux :
ostream& operator << ( ostream& os, const object& o ) {
return os << o.toString();
}
la problématique, d'accès concurrentiel notamment, sera (quasiment) exactement la même pour coder le ostream& << (ostream&, Object&); (quasiment car le problème de la chaine retournée n'existe que pour l'appel à une fonction).
A 1h00 du matin et rapidement, je n'ai pas trouvé les mêmes problèmes dans ces deux approches.
J'imaginais quelque chose comme ça pour toString() : const char* object::toString() const { ... return quelquechose; }
oui, quelque chose cela, où "..." n'est pas char* quelquechose = new char[aLength]; sprintf(quelquechose, "<format>", members);
ni string quelquechose; quelquechose << members; (~quelquechose sera appelé avant le <<(const char*))
et là je ne vois pas trop de solution simple notamment pour la concurence sur un hypothétique buffer static (un peu à la "C" je dirais)
pour éviter la ""complexité"" d'une string interne (et/ou par étourderie) on pourrait se contenter d'un buffer global static, ce serait là une erreur en effet.
un tel buffer (unique) fournirait des contenus invalides en cas d'accès concurrentiel à 'la' méthode toString par différentes instances; je pensais également à des accès concurrentiels sur la même instance (le même object dumpé par plusieurs threads en même temps), là toutes les variantes listées ici échouent.
alors qu'avec un std::string object::toString() const { // ou asString(), j'hésite toujours. string tmp; // ... return tmp; }
c'est une option possible, elle évite une donnée membre String, et limite la problématique des accès concurrentiels au seul temps du remplissage de 'tmp'.
pour ma part, j'hésiterai un peu en faveur de la première façon car "std::string" n'est pas (pour moi et même si pour moi seul) un type standard, comme l'est un const char*; utiliser un string en interne à ma méthode est ma toutouille et me va, forcer l'utilisateur externe à connaitre ce type, ne me convient pas.
puis, pour faciliter une utilisation en mode flux : ostream& operator << ( ostream& os, const object& o ) { return os << o.toString(); }
J'ai du mal à te suivre : Tu prones une sois disant simplicité, mais alors que dans mon exemple, on doit une seule fois surcharger 2 fonctions d'un streambuf, au lieu d'écrire 1 fonction à paramètres variables (la complexité plus élevée est discutable), dans le tiens, à chaque classe tu demandes à l'utilisateur d'écrire une fonction toString et d'ajouter nue variable membre, cette fonction passant par des ostringstreams, que tu as éludé en écrivant _dump << member1, avec _dump une variable d'une classe String non définie, là où je réutilise le mécanisme standard d'écrire dans un flux.
Donc si je t'ai suivi, tu écris dans un flux pour mettre dans une string pour mettre dans un char*, et tu trouve ça plus simple que d'écrire directement dans un flux ?
J'ai du mal à te suivre : Tu prones une sois disant simplicité, mais
alors que dans mon exemple, on doit une seule fois surcharger 2
fonctions d'un streambuf, au lieu d'écrire 1 fonction à paramètres
variables (la complexité plus élevée est discutable), dans le tiens, à
chaque classe tu demandes à l'utilisateur d'écrire une fonction toString
et d'ajouter nue variable membre, cette fonction passant par des
ostringstreams, que tu as éludé en écrivant _dump << member1, avec _dump
une variable d'une classe String non définie, là où je réutilise le
mécanisme standard d'écrire dans un flux.
Donc si je t'ai suivi, tu écris dans un flux pour mettre dans une string
pour mettre dans un char*, et tu trouve ça plus simple que d'écrire
directement dans un flux ?
J'ai du mal à te suivre : Tu prones une sois disant simplicité, mais alors que dans mon exemple, on doit une seule fois surcharger 2 fonctions d'un streambuf, au lieu d'écrire 1 fonction à paramètres variables (la complexité plus élevée est discutable), dans le tiens, à chaque classe tu demandes à l'utilisateur d'écrire une fonction toString et d'ajouter nue variable membre, cette fonction passant par des ostringstreams, que tu as éludé en écrivant _dump << member1, avec _dump une variable d'une classe String non définie, là où je réutilise le mécanisme standard d'écrire dans un flux.
Donc si je t'ai suivi, tu écris dans un flux pour mettre dans une string pour mettre dans un char*, et tu trouve ça plus simple que d'écrire directement dans un flux ?
-- Loïc
Loïc Joly
David wrote on 25/11/2006 00:55:
J'imaginais quelque chose comme ça pour toString() : const char* object::toString() const { ... return quelquechose; }
j'ai répondu sur cette hypothèse d'un retour "const char*" (que je peux en effet parfois préférer).
ce n'était pas dans mes réponses précédentes; on peut partir, bien sur, sur un retour std::string, qui, par recopie, donne le résultat attendu.
Et n'est pas utilisable directement dans un printf...
-- Loïc
David wrote on 25/11/2006 00:55:
J'imaginais quelque chose comme ça pour toString() :
const char* object::toString() const {
...
return quelquechose; }
j'ai répondu sur cette hypothèse d'un retour "const char*" (que je peux
en effet parfois préférer).
ce n'était pas dans mes réponses précédentes; on peut partir, bien sur,
sur un retour std::string, qui, par recopie, donne le résultat attendu.
Et n'est pas utilisable directement dans un printf...
J'imaginais quelque chose comme ça pour toString() : const char* object::toString() const { ... return quelquechose; }
j'ai répondu sur cette hypothèse d'un retour "const char*" (que je peux en effet parfois préférer).
ce n'était pas dans mes réponses précédentes; on peut partir, bien sur, sur un retour std::string, qui, par recopie, donne le résultat attendu.
Et n'est pas utilisable directement dans un printf...
-- Loïc
Loïc Joly
Loïc Joly wrote on 24/11/2006 23:14:
En général, ce que j'aime logger ressemble plus à : "Itération 3 : Objet = {1, 3, "Toto", true}" Et que j'aime écrire : log << "Iteration " << i << " : Object = " << object;
Je ne sais pas écrire la même chose simplement avec printf.
*tu* ne sais pas, et alors ? d'autre sauront écrire printf("Iteration %d : Object = %s", i, object.toString()); (en essayant de donner un sens à "log << object" qui ne peut rien dire à sa seule lecture (obfuscation ici non décriée)).
Envoyer une donnéee sur un flux, tu appelle ça de l'obfuscation ?! C'est pourtant un des mécanismes de base du langage.
-- Loïc
Loïc Joly wrote on 24/11/2006 23:14:
En général, ce que j'aime logger ressemble plus à :
"Itération 3 : Objet = {1, 3, "Toto", true}"
Et que j'aime écrire :
log << "Iteration " << i << " : Object = " << object;
Je ne sais pas écrire la même chose simplement avec printf.
*tu* ne sais pas, et alors ?
d'autre sauront écrire
printf("Iteration %d : Object = %s", i, object.toString());
(en essayant de donner un sens à "log << object" qui ne peut rien dire à
sa seule lecture (obfuscation ici non décriée)).
Envoyer une donnéee sur un flux, tu appelle ça de l'obfuscation ?! C'est
pourtant un des mécanismes de base du langage.
En général, ce que j'aime logger ressemble plus à : "Itération 3 : Objet = {1, 3, "Toto", true}" Et que j'aime écrire : log << "Iteration " << i << " : Object = " << object;
Je ne sais pas écrire la même chose simplement avec printf.
*tu* ne sais pas, et alors ? d'autre sauront écrire printf("Iteration %d : Object = %s", i, object.toString()); (en essayant de donner un sens à "log << object" qui ne peut rien dire à sa seule lecture (obfuscation ici non décriée)).
Envoyer une donnéee sur un flux, tu appelle ça de l'obfuscation ?! C'est pourtant un des mécanismes de base du langage.
-- Loïc
Sylvain
Loïc Joly wrote on 25/11/2006 09:37:
J'ai du mal à te suivre : Tu prones une sois disant simplicité, ...
2 points ont été mélangés via ton post: - le PO demandait comment traiter des pamarètres variables (réponse va_list) et comment les mettre en forme (réponse vsprintf) - tu as critiqué cette façon de faire en y opposant le dump d'un object.
j'ai déjà largement exposé ici, notamment dans des échanges avec James, que je sépare généralement la mise en forme d'un objet (sa représentation, pouvant varier selon le besoin, d'où le switch) du log/stockage/envoi de cette information formattée.
cette distinction faite, et si on veut argumenter sur le dump d'un objet, la mise en forme du dump de celui-ci devra être faite quelque soit la façon dont je l'envoie, le print, le log, ..., il n'y a de simplicité obligeatoire et nécessaire ici, si l'objet (et/ou les besoins d'informations sur cet objet) est compliqué, la génération de son dump sera compliqué; par contre transmettre ce dump pourra être "aussi simple" qu'un printf("%s", ...) si ce contexte de transmission n'a pas besoin / n'est pas basé sur des iostreams.
... alors que dans mon exemple, on doit une seule fois surcharger 2 fonctions d'un streambuf, au lieu d'écrire 1 fonction à paramètres variables (la complexité plus élevée est discutable), dans le tiens, à chaque classe tu demandes à l'utilisateur d'écrire une fonction toString et d'ajouter nue variable membre, cette fonction passant par des ostringstreams, que tu as éludé en écrivant _dump << member1, avec _dump une variable d'une classe String non définie, là où je réutilise le mécanisme standard d'écrire dans un flux.
on est d'accord - j'espère - sur le fait que la classe devra soit: - fournir un operateur d'injection vers ostream (ton modèle) - fournir une methode toString() (mon exemple) le contenu de ces 2 fonctions/méthodes sera identique; il n'y a donc pas critères déterminants de choix à ce niveau.
factuellement: - une variable membre est nécessaire que si le type retourné est const char* (là j'ai suivi l'idée de David, je ne l'ai pas imposé a priori) et variable (un log possible pour la classe 'Toto' pourrait être /return "Toto";/ (chaîne C static que l'on utiliserait par exemple pour vérifier que la bonne classe (d'un schéma d'héritage) est utilisée). - je n'élude pas le dump de l'objet, je répète que c'est une opération en soi (indépendante de sa transmission) et qu'elle est variable (de la chaine constante ou formattage complet de tous ses membres, en passant par le TLV, requete SQL et autre XML déjà évoqué pour le même sujet). - la classe String est ma classe wrapper de chaine de caractères, je n'utilise jamais std::string, j'ai laissé ce nom ici car il est suffisant pour permettre à tout le monde de comprendre son role.
Donc si je t'ai suivi, tu écris dans un flux pour mettre dans une string pour mettre dans un char*, et tu trouve ça plus simple que d'écrire directement dans un flux ?
encore une fois, il y a (IMHO) ici une mélange des roles: - 'fluxer' l'objet, j'ai besoin quelque soit le reste de faire cette opération - logger l'information, ici prétendre "écrire dans un flux" ne répond pas du tout: si "l'écriture sur le flux" est un log système (type OutputDebugString) tu ne le réalises pas, si c'est une écriture en base (le dump est une clause INSERT par exemple) tu ne leréalises pas plus.
je serais donc d'accord avec toi pour dire que l'écriture: log << "Iteration " << i << " : Object = " << object; apparait simple, l'honnêteté voudra que l'on précise que cela peut être suffisant si et seulement si "log" est un "std::cout" (avec un marqueur de fin d'injection cela pourrait être plus).
Sylvain.
Loïc Joly wrote on 25/11/2006 09:37:
J'ai du mal à te suivre : Tu prones une sois disant simplicité, ...
2 points ont été mélangés via ton post:
- le PO demandait comment traiter des pamarètres variables (réponse
va_list) et comment les mettre en forme (réponse vsprintf)
- tu as critiqué cette façon de faire en y opposant le dump d'un object.
j'ai déjà largement exposé ici, notamment dans des échanges avec James,
que je sépare généralement la mise en forme d'un objet (sa
représentation, pouvant varier selon le besoin, d'où le switch) du
log/stockage/envoi de cette information formattée.
cette distinction faite, et si on veut argumenter sur le dump d'un
objet, la mise en forme du dump de celui-ci devra être faite quelque
soit la façon dont je l'envoie, le print, le log, ..., il n'y a de
simplicité obligeatoire et nécessaire ici, si l'objet (et/ou les besoins
d'informations sur cet objet) est compliqué, la génération de son dump
sera compliqué; par contre transmettre ce dump pourra être "aussi
simple" qu'un printf("%s", ...) si ce contexte de transmission n'a pas
besoin / n'est pas basé sur des iostreams.
... alors que dans mon exemple, on doit une seule fois surcharger 2
fonctions d'un streambuf, au lieu d'écrire 1 fonction à paramètres
variables (la complexité plus élevée est discutable), dans le tiens, à
chaque classe tu demandes à l'utilisateur d'écrire une fonction toString
et d'ajouter nue variable membre, cette fonction passant par des
ostringstreams, que tu as éludé en écrivant _dump << member1, avec _dump
une variable d'une classe String non définie, là où je réutilise le
mécanisme standard d'écrire dans un flux.
on est d'accord - j'espère - sur le fait que la classe devra soit:
- fournir un operateur d'injection vers ostream (ton modèle)
- fournir une methode toString() (mon exemple)
le contenu de ces 2 fonctions/méthodes sera identique; il n'y a donc pas
critères déterminants de choix à ce niveau.
factuellement:
- une variable membre est nécessaire que si le type retourné est const
char* (là j'ai suivi l'idée de David, je ne l'ai pas imposé a priori) et
variable (un log possible pour la classe 'Toto' pourrait être /return
"Toto";/ (chaîne C static que l'on utiliserait par exemple pour vérifier
que la bonne classe (d'un schéma d'héritage) est utilisée).
- je n'élude pas le dump de l'objet, je répète que c'est une opération
en soi (indépendante de sa transmission) et qu'elle est variable (de la
chaine constante ou formattage complet de tous ses membres, en passant
par le TLV, requete SQL et autre XML déjà évoqué pour le même sujet).
- la classe String est ma classe wrapper de chaine de caractères, je
n'utilise jamais std::string, j'ai laissé ce nom ici car il est
suffisant pour permettre à tout le monde de comprendre son role.
Donc si je t'ai suivi, tu écris dans un flux pour mettre dans une string
pour mettre dans un char*, et tu trouve ça plus simple que d'écrire
directement dans un flux ?
encore une fois, il y a (IMHO) ici une mélange des roles:
- 'fluxer' l'objet, j'ai besoin quelque soit le reste de faire cette
opération
- logger l'information, ici prétendre "écrire dans un flux" ne répond
pas du tout: si "l'écriture sur le flux" est un log système (type
OutputDebugString) tu ne le réalises pas, si c'est une écriture en base
(le dump est une clause INSERT par exemple) tu ne leréalises pas plus.
je serais donc d'accord avec toi pour dire que l'écriture:
log << "Iteration " << i << " : Object = " << object;
apparait simple, l'honnêteté voudra que l'on précise que cela peut être
suffisant si et seulement si "log" est un "std::cout" (avec un marqueur
de fin d'injection cela pourrait être plus).
J'ai du mal à te suivre : Tu prones une sois disant simplicité, ...
2 points ont été mélangés via ton post: - le PO demandait comment traiter des pamarètres variables (réponse va_list) et comment les mettre en forme (réponse vsprintf) - tu as critiqué cette façon de faire en y opposant le dump d'un object.
j'ai déjà largement exposé ici, notamment dans des échanges avec James, que je sépare généralement la mise en forme d'un objet (sa représentation, pouvant varier selon le besoin, d'où le switch) du log/stockage/envoi de cette information formattée.
cette distinction faite, et si on veut argumenter sur le dump d'un objet, la mise en forme du dump de celui-ci devra être faite quelque soit la façon dont je l'envoie, le print, le log, ..., il n'y a de simplicité obligeatoire et nécessaire ici, si l'objet (et/ou les besoins d'informations sur cet objet) est compliqué, la génération de son dump sera compliqué; par contre transmettre ce dump pourra être "aussi simple" qu'un printf("%s", ...) si ce contexte de transmission n'a pas besoin / n'est pas basé sur des iostreams.
... alors que dans mon exemple, on doit une seule fois surcharger 2 fonctions d'un streambuf, au lieu d'écrire 1 fonction à paramètres variables (la complexité plus élevée est discutable), dans le tiens, à chaque classe tu demandes à l'utilisateur d'écrire une fonction toString et d'ajouter nue variable membre, cette fonction passant par des ostringstreams, que tu as éludé en écrivant _dump << member1, avec _dump une variable d'une classe String non définie, là où je réutilise le mécanisme standard d'écrire dans un flux.
on est d'accord - j'espère - sur le fait que la classe devra soit: - fournir un operateur d'injection vers ostream (ton modèle) - fournir une methode toString() (mon exemple) le contenu de ces 2 fonctions/méthodes sera identique; il n'y a donc pas critères déterminants de choix à ce niveau.
factuellement: - une variable membre est nécessaire que si le type retourné est const char* (là j'ai suivi l'idée de David, je ne l'ai pas imposé a priori) et variable (un log possible pour la classe 'Toto' pourrait être /return "Toto";/ (chaîne C static que l'on utiliserait par exemple pour vérifier que la bonne classe (d'un schéma d'héritage) est utilisée). - je n'élude pas le dump de l'objet, je répète que c'est une opération en soi (indépendante de sa transmission) et qu'elle est variable (de la chaine constante ou formattage complet de tous ses membres, en passant par le TLV, requete SQL et autre XML déjà évoqué pour le même sujet). - la classe String est ma classe wrapper de chaine de caractères, je n'utilise jamais std::string, j'ai laissé ce nom ici car il est suffisant pour permettre à tout le monde de comprendre son role.
Donc si je t'ai suivi, tu écris dans un flux pour mettre dans une string pour mettre dans un char*, et tu trouve ça plus simple que d'écrire directement dans un flux ?
encore une fois, il y a (IMHO) ici une mélange des roles: - 'fluxer' l'objet, j'ai besoin quelque soit le reste de faire cette opération - logger l'information, ici prétendre "écrire dans un flux" ne répond pas du tout: si "l'écriture sur le flux" est un log système (type OutputDebugString) tu ne le réalises pas, si c'est une écriture en base (le dump est une clause INSERT par exemple) tu ne leréalises pas plus.
je serais donc d'accord avec toi pour dire que l'écriture: log << "Iteration " << i << " : Object = " << object; apparait simple, l'honnêteté voudra que l'on précise que cela peut être suffisant si et seulement si "log" est un "std::cout" (avec un marqueur de fin d'injection cela pourrait être plus).
Sylvain.
Sylvain
Loïc Joly wrote on 25/11/2006 09:38:
[] on peut partir, sur un retour std::string, qui donne le résultat attendu.
Et n'est pas utilisable directement dans un printf...
?! parce qu'il n'a pas d'opérateurs de coercion vers const char* ? une raison de plus (pour moi) de ne pas l'utiliser.
Sylvain.
Loïc Joly wrote on 25/11/2006 09:38:
[] on peut partir, sur un retour std::string,
qui donne le résultat attendu.
Et n'est pas utilisable directement dans un printf...
?! parce qu'il n'a pas d'opérateurs de coercion vers const char* ?
une raison de plus (pour moi) de ne pas l'utiliser.
[] on peut partir, sur un retour std::string, qui donne le résultat attendu.
Et n'est pas utilisable directement dans un printf...
?! parce qu'il n'a pas d'opérateurs de coercion vers const char* ? une raison de plus (pour moi) de ne pas l'utiliser.
Je ne vois pas vraiment le rapport entre un operateur de conversion automatique vers const char* et la compatibilité avec printf.
Jean-Marc Bourguet
Michel Decima writes:
Sylvain wrote:
Loïc Joly wrote on 25/11/2006 09:38:
[] on peut partir, sur un retour std::string, qui donne le résultat attendu.
Et n'est pas utilisable directement dans un printf... ?! parce qu'il n'a pas d'opérateurs de coercion vers const char* ?
une raison de plus (pour moi) de ne pas l'utiliser.
Je ne vois pas vraiment le rapport entre un operateur de conversion automatique vers const char* et la compatibilité avec printf.
Il n'y en a pas. Passer une instance de classe à une fonction variadique, c'est un comportement indéfini, quelles que soient les conversions implicites disponibles pour cette classe.
A+
-- 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
Michel Decima <michel.decima@wanadoo.fr> writes:
Sylvain wrote:
Loïc Joly wrote on 25/11/2006 09:38:
[] on peut partir, sur un retour std::string, qui donne le résultat
attendu.
Et n'est pas utilisable directement dans un printf...
?! parce qu'il n'a pas d'opérateurs de coercion vers const char* ?
une raison de plus (pour moi) de ne pas l'utiliser.
Je ne vois pas vraiment le rapport entre un operateur de conversion
automatique vers const char* et la compatibilité avec printf.
Il n'y en a pas. Passer une instance de classe à une fonction variadique,
c'est un comportement indéfini, quelles que soient les conversions
implicites disponibles pour cette classe.
A+
--
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
[] on peut partir, sur un retour std::string, qui donne le résultat attendu.
Et n'est pas utilisable directement dans un printf... ?! parce qu'il n'a pas d'opérateurs de coercion vers const char* ?
une raison de plus (pour moi) de ne pas l'utiliser.
Je ne vois pas vraiment le rapport entre un operateur de conversion automatique vers const char* et la compatibilité avec printf.
Il n'y en a pas. Passer une instance de classe à une fonction variadique, c'est un comportement indéfini, quelles que soient les conversions implicites disponibles pour cette classe.
A+
-- 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
Sylvain
Michel Decima wrote on 25/11/2006 20:35:
Sylvain wrote:
Loïc Joly wrote on 25/11/2006 09:38:
[] on peut partir, sur un retour std::string, qui donne le résultat attendu.
Et n'est pas utilisable directement dans un printf...
?! parce qu'il n'a pas d'opérateurs de coercion vers const char* ? une raison de plus (pour moi) de ne pas l'utiliser.
Je ne vois pas vraiment le rapport entre un operateur de conversion automatique vers const char* et la compatibilité avec printf.
je ne vois pas non plus vraiment ce que Loïc a voulu dire ... mais il n'a pas dit "compatible" (pour lequel je vois encore moins le rapport) mais "utilisable".
"directement" voulait peut-être signifier sans utiliser un getLeBouzinInterne() -- ça doit exister ça non ?
Sylvain.
Michel Decima wrote on 25/11/2006 20:35:
Sylvain wrote:
Loïc Joly wrote on 25/11/2006 09:38:
[] on peut partir, sur un retour std::string, qui donne le résultat
attendu.
Et n'est pas utilisable directement dans un printf...
?! parce qu'il n'a pas d'opérateurs de coercion vers const char* ?
une raison de plus (pour moi) de ne pas l'utiliser.
Je ne vois pas vraiment le rapport entre un operateur de conversion
automatique vers const char* et la compatibilité avec printf.
je ne vois pas non plus vraiment ce que Loïc a voulu dire ...
mais il n'a pas dit "compatible" (pour lequel je vois encore moins le
rapport) mais "utilisable".
"directement" voulait peut-être signifier sans utiliser un
getLeBouzinInterne() -- ça doit exister ça non ?
[] on peut partir, sur un retour std::string, qui donne le résultat attendu.
Et n'est pas utilisable directement dans un printf...
?! parce qu'il n'a pas d'opérateurs de coercion vers const char* ? une raison de plus (pour moi) de ne pas l'utiliser.
Je ne vois pas vraiment le rapport entre un operateur de conversion automatique vers const char* et la compatibilité avec printf.
je ne vois pas non plus vraiment ce que Loïc a voulu dire ... mais il n'a pas dit "compatible" (pour lequel je vois encore moins le rapport) mais "utilisable".
"directement" voulait peut-être signifier sans utiliser un getLeBouzinInterne() -- ça doit exister ça non ?