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.
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.
- 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).
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.
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.
- 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).
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.
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.
- 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).
Indefini ne veut d'ailleurs pas dire aleatoire ni non deterministe. Ca
veut dire que la norme n'impose rien aux implementations; et en pratique ca
veut dire que les implementations ne le definissent souvent pas et se
permettent de changer de comportement d'une version a l'autre ou en
fonctions de facteurs qu'elles ne prennent pas la peine d'annoncer.
Le code que j'ecris est delivre avec 3 compilateurs differents (c'etait 4
il n'y a pas si longtemps). De ces 3 compilateurs, 2 donnent un
avertissement et un genere du code qui plante. Ce n'est pas un exercice
scolaire ni une speculation futuriste.
Mais je suis en effet tout a fait hors de la logique qui consiste a code en
fonction de ce que le compilateur que j'ai sous la main a l'air de faire.
Utiliser cette logique serait dans mon cas tout a fait irresponsable.
Je cite donc une référence qui me semble appuyer mon propos en
précisant qu'il est possible que j'ai manqué quelque chose qui complète
la référence en introduisant un cas particulier -- les exemples dans la
norme de ce genre de choses sont légions. Je m'attendais à ce que tu
cites quelque chose appuyant ton point de vue (pas nécessairement la
norme -- pour moi c'est la référence où c'est le plus aisé de trouvé
quelque chose et la plus facile à citer parce qu'elle est sous forme de
pdf) mais tu me traites d'ignare, à moins que tu ne considères que je
t'ai traité d'ignare?
option 2 (non prise à titre personnel).
J'ai du mal a suivre ton raisonnement...
Mais le compilateur qui gene est celui que nous utilisons pour une des
plateformes sur lesquelles nous delivrons, que tu le veuilles ou non.
[...] Par ailleurs, le compilateur sur lequel le code a l'air
de faire ce que tu veux [] sans donne un seul avertissement
est au contraire renomme pour sa rigueur.
Indefini ne veut d'ailleurs pas dire aleatoire ni non deterministe. Ca
veut dire que la norme n'impose rien aux implementations; et en pratique ca
veut dire que les implementations ne le definissent souvent pas et se
permettent de changer de comportement d'une version a l'autre ou en
fonctions de facteurs qu'elles ne prennent pas la peine d'annoncer.
Le code que j'ecris est delivre avec 3 compilateurs differents (c'etait 4
il n'y a pas si longtemps). De ces 3 compilateurs, 2 donnent un
avertissement et un genere du code qui plante. Ce n'est pas un exercice
scolaire ni une speculation futuriste.
Mais je suis en effet tout a fait hors de la logique qui consiste a code en
fonction de ce que le compilateur que j'ai sous la main a l'air de faire.
Utiliser cette logique serait dans mon cas tout a fait irresponsable.
Je cite donc une référence qui me semble appuyer mon propos en
précisant qu'il est possible que j'ai manqué quelque chose qui complète
la référence en introduisant un cas particulier -- les exemples dans la
norme de ce genre de choses sont légions. Je m'attendais à ce que tu
cites quelque chose appuyant ton point de vue (pas nécessairement la
norme -- pour moi c'est la référence où c'est le plus aisé de trouvé
quelque chose et la plus facile à citer parce qu'elle est sous forme de
pdf) mais tu me traites d'ignare, à moins que tu ne considères que je
t'ai traité d'ignare?
option 2 (non prise à titre personnel).
J'ai du mal a suivre ton raisonnement...
Mais le compilateur qui gene est celui que nous utilisons pour une des
plateformes sur lesquelles nous delivrons, que tu le veuilles ou non.
[...] Par ailleurs, le compilateur sur lequel le code a l'air
de faire ce que tu veux [] sans donne un seul avertissement
est au contraire renomme pour sa rigueur.
Indefini ne veut d'ailleurs pas dire aleatoire ni non deterministe. Ca
veut dire que la norme n'impose rien aux implementations; et en pratique ca
veut dire que les implementations ne le definissent souvent pas et se
permettent de changer de comportement d'une version a l'autre ou en
fonctions de facteurs qu'elles ne prennent pas la peine d'annoncer.
Le code que j'ecris est delivre avec 3 compilateurs differents (c'etait 4
il n'y a pas si longtemps). De ces 3 compilateurs, 2 donnent un
avertissement et un genere du code qui plante. Ce n'est pas un exercice
scolaire ni une speculation futuriste.
Mais je suis en effet tout a fait hors de la logique qui consiste a code en
fonction de ce que le compilateur que j'ai sous la main a l'air de faire.
Utiliser cette logique serait dans mon cas tout a fait irresponsable.
Je cite donc une référence qui me semble appuyer mon propos en
précisant qu'il est possible que j'ai manqué quelque chose qui complète
la référence en introduisant un cas particulier -- les exemples dans la
norme de ce genre de choses sont légions. Je m'attendais à ce que tu
cites quelque chose appuyant ton point de vue (pas nécessairement la
norme -- pour moi c'est la référence où c'est le plus aisé de trouvé
quelque chose et la plus facile à citer parce qu'elle est sous forme de
pdf) mais tu me traites d'ignare, à moins que tu ne considères que je
t'ai traité d'ignare?
option 2 (non prise à titre personnel).
J'ai du mal a suivre ton raisonnement...
Mais le compilateur qui gene est celui que nous utilisons pour une des
plateformes sur lesquelles nous delivrons, que tu le veuilles ou non.
[...] Par ailleurs, le compilateur sur lequel le code a l'air
de faire ce que tu veux [] sans donne un seul avertissement
est au contraire renomme pour sa rigueur.
Sylvain wrote:static char message[2048];
_vsnprintf(message, 2048, pattern, params);
[...]
OutputDebugString(message);
N'y a-t-il pas une astuce comme quoi sur certaines implémentations il
n'est pas garanti que vsnprintf va écrire le zéro terminal quand le
buffer déborde ?
Sylvain wrote:
static char message[2048];
_vsnprintf(message, 2048, pattern, params);
[...]
OutputDebugString(message);
N'y a-t-il pas une astuce comme quoi sur certaines implémentations il
n'est pas garanti que vsnprintf va écrire le zéro terminal quand le
buffer déborde ?
Sylvain wrote:static char message[2048];
_vsnprintf(message, 2048, pattern, params);
[...]
OutputDebugString(message);
N'y a-t-il pas une astuce comme quoi sur certaines implémentations il
n'est pas garanti que vsnprintf va écrire le zéro terminal quand le
buffer déborde ?
Le PO demandait une méthode pour améliorer les possibilités de formatage
quand on envoie des données vers la console de débug. Il proposais une
syntaxe alternative, je lui en ai proposé une autre.
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.
Moi aussi : L'opérateur << ne se charge que de la mise en forme, le fait
que je l'applique à un cout, file, log, autre... se charge de l'endroit
d'envoi. C'est le principe de base du découpage des flux en xstream et
xstreambuf. C'est d'ailleur un de mes reproches à printf qu'il ne gère
pas cette séparation.
[...]
Je ne suis pas d'accord. Dans mon cas, log n'était absolument pas cout,
mais une instance d'une classe dérivée de ostream et écrite de telle
façon qu'elle utilise OutputDebugString pour ses sorties.
Ou mieux () encore qu'elle soit configurable pour logger vers
différentes destinations en fonction de la configuration de
l'utilisateur final de l'outil.
Pour l'histoire de marqueur de fin d'injection, si j'ai bien compris ce
que tu veux dire, un saut de ligne me suffit généralement pour les
aspects mise en forme du flux, et pour les aspects bufferisation, a
priori, un objet servant à du log, j'éviterai de lui adjoindre un buffer
plus long qu'une ligne. Si je n'ai pas compris, n'hésite pas à
développer ta pensée.
Le PO demandait une méthode pour améliorer les possibilités de formatage
quand on envoie des données vers la console de débug. Il proposais une
syntaxe alternative, je lui en ai proposé une autre.
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.
Moi aussi : L'opérateur << ne se charge que de la mise en forme, le fait
que je l'applique à un cout, file, log, autre... se charge de l'endroit
d'envoi. C'est le principe de base du découpage des flux en xstream et
xstreambuf. C'est d'ailleur un de mes reproches à printf qu'il ne gère
pas cette séparation.
[...]
Je ne suis pas d'accord. Dans mon cas, log n'était absolument pas cout,
mais une instance d'une classe dérivée de ostream et écrite de telle
façon qu'elle utilise OutputDebugString pour ses sorties.
Ou mieux () encore qu'elle soit configurable pour logger vers
différentes destinations en fonction de la configuration de
l'utilisateur final de l'outil.
Pour l'histoire de marqueur de fin d'injection, si j'ai bien compris ce
que tu veux dire, un saut de ligne me suffit généralement pour les
aspects mise en forme du flux, et pour les aspects bufferisation, a
priori, un objet servant à du log, j'éviterai de lui adjoindre un buffer
plus long qu'une ligne. Si je n'ai pas compris, n'hésite pas à
développer ta pensée.
Le PO demandait une méthode pour améliorer les possibilités de formatage
quand on envoie des données vers la console de débug. Il proposais une
syntaxe alternative, je lui en ai proposé une autre.
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.
Moi aussi : L'opérateur << ne se charge que de la mise en forme, le fait
que je l'applique à un cout, file, log, autre... se charge de l'endroit
d'envoi. C'est le principe de base du découpage des flux en xstream et
xstreambuf. C'est d'ailleur un de mes reproches à printf qu'il ne gère
pas cette séparation.
[...]
Je ne suis pas d'accord. Dans mon cas, log n'était absolument pas cout,
mais une instance d'une classe dérivée de ostream et écrite de telle
façon qu'elle utilise OutputDebugString pour ses sorties.
Ou mieux () encore qu'elle soit configurable pour logger vers
différentes destinations en fonction de la configuration de
l'utilisateur final de l'outil.
Pour l'histoire de marqueur de fin d'injection, si j'ai bien compris ce
que tu veux dire, un saut de ligne me suffit généralement pour les
aspects mise en forme du flux, et pour les aspects bufferisation, a
priori, un objet servant à du log, j'éviterai de lui adjoindre un buffer
plus long qu'une ligne. Si je n'ai pas compris, n'hésite pas à
développer ta pensée.
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).
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).
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).
mais juste de tracer (par exemple) si l'on rentre ou non dans une fonction
qui ne peut pas être tracée sous debugger symbolique.
mais juste de tracer (par exemple) si l'on rentre ou non dans une fonction
qui ne peut pas être tracée sous debugger symbolique.
mais juste de tracer (par exemple) si l'on rentre ou non dans une fonction
qui ne peut pas être tracée sous debugger symbolique.