IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Flux et préprocesseur .


Sujet :

C++

  1. #1
    Membre éclairé
    Inscrit en
    Octobre 2004
    Messages
    616
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 616
    Par défaut Flux et préprocesseur .
    Bonjour, toujours dans le but d'écrire une classe de type " logger" pour mon projet, je me suis heurté a quelques problèmes de conceptions .

    J'aimerai obtenir une syntaxe proche de ca :

    Log(FILE|CONSOLE,WARNING) << "Ma variable i vaux : " << i << "\n" ;

    Bah c'est pas facile ....


    Je me heurte a plusieurs problèmes :

    Le premier :
    - Je veux que certains lod ne soit pas présent lors d'un build ( debug/release peut importe ) . Par exemple, que tout ceux dont le type est " WARNING , ou MISC" soit enlevé, mais que je garde ceux nommé "ERROR" par exemple ).

    Typiquement, je ne vois pas comment ( si c'est possible ... ) gardé certaine lignes en fonction d'un argument :
    ex : Test(a)

    ( test étant une macro, je veux garder seulement lors d'un build les Test(a) avec a =2, le reste je n'en veux pas ... )

    [ je veux eviter de devoir passer par un Log_Warning(...) Log_Error(...) ]


    Ensuite, j'ai du mal avec les flux . Je ne vois pas comment m'en sortir proprement .
    Avec une ligne de code tel que je l'ai énoncé en debut de post, je veux pouvoir aboutir à l'apelle d'une fonction ( ou de plusieur, selon les flag en paramètre ) de ce type:

    WriteConsole(...)
    WriteFile(...)

    Avec en paramètre :
    Un string représentant le message TOTAL ( dans mon cas et pour i = 12 )
    MsgString = "Ma variable i vaux 12 \n"
    ET certaines macro en paramètre ( genre __FILE__, __LINE__ ... )

    bref une fonction de ce type :
    WriteFile(int EventType ,string Msg, const char * Line, const char * File )

    [ EventType étant : WARNING , ERROR, MISC ... ect ... ]

    En gros ce qu'il me manque, c'est le lien entre le chainage de flux et l'apelle a Write()

    Résumer : Comment a l'aide de macro, ne pas "expand" ma macro selon la velur d'un de ces paramètre ? Et comment reconsituer mon message lors d'un chainage de flux ? [ et accesoirement, comment extraire proprement mes types d'ouput ( FILE , CONSOLE , SCREEN ... ) de ma macro .

    Je suis sur que ce n'est pas clair ... mais merci quand même
    [ je referai ce soir quelque chose de plus propre si c'est vraiment trop le bordel . ]

  2. #2
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Pour ton premier problème, le seul moyen que je vois est de jouer avec la spécialisation des templates. Ce qui implique -- mais tu devais déjà le savoir -- que le deuxième argument devra toujours être constant.

    Pour le deuxième problème, le seul moyen d'utiliser __FILE__ et __LINE__ c'est que l'expansion de Log les contiennent.

    Quand à la l'envoi du message, soit tu le synchronise avec la destruction d'un objet temporaire créé par Log (ce qui a l'inconvénient de ne pas pouvoir bâtir un message en plusieurs fois). Soit tu le fais quand ton streambuf recois un flush.

  3. #3
    Membre éclairé
    Inscrit en
    Octobre 2004
    Messages
    616
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 616
    Par défaut
    Merci :
    Pour ton premier problème, le seul moyen que je vois est de jouer avec la spécialisation des templates. Ce qui implique -- mais tu devais déjà le savoir -- que le deuxième argument devra toujours être constant.
    En fait je ne vois pas de quel genre de solution tu parle, et de plus, mes 2 paramètres sont variables ...

    Je peux procéder ainsi sinon, mais ca ne résoud pas le problème, car ca me génère un "if", même lorsque je veux totalement eradiqué ce genre de log :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define Log(p) if(p=="WARNING" || p =="ERROR") std::cout << p << std::endl ;
    Pour le deuxième problème, le seul moyen d'utiliser __FILE__ et __LINE__ c'est que l'expansion de Log les contiennent.
    Je me suis mal exprimé, car ca , j'en suis bien au courant

    Quand à la l'envoi du message, soit tu le synchronise avec la destruction d'un objet temporaire créé par Log (ce qui a l'inconvénient de ne pas pouvoir bâtir un message en plusieurs fois). Soit tu le fais quand ton streambuf recois un flush.
    Ca, ca demande réflexion parcontre je vais voir si il y a moyen de faire qquchose comme ca, sans alourdir la syntaxe de mon log .

  4. #4
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Clad3
    En fait je ne vois pas de quel genre de solution tu parle, et de plus, mes 2 paramètres sont variables ...
    Si le deuxième paramètre peut être calculé tout juste avant l'appel, je me demande comment tu peux rêver éliminer tout code suivant sa valeur.
    S'il est constant, je voulais m'en servir comme paramètre template, et avoir des spécialisations explicites qui suppriment tout le code pour autant que le compilateur ne soit pas trop mauvais dans l'inlining de fonctions complètement vides.

    Au fait, je crois que boost a quelque chose pour les logs.

  5. #5
    Membre éclairé
    Inscrit en
    Octobre 2004
    Messages
    616
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 616
    Par défaut
    Oui j'avais mal compris, en effet mes 2 paramètres sont connu à la compilation

    Enfin cela-dit, j'ai toujours du mal a voir quel genre de code tu veux produire, tu aurais un petit exemple, histoire de me dé-flouter ?

  6. #6
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Clad3
    Enfin cela-dit, j'ai toujours du mal a voir quel genre de code tu veux produire, tu aurais un petit exemple, histoire de me dé-flouter ?
    Quelque chose du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    template <bool dropItAll> struct Logger;
    template<> struct Logger<true> {
       Logger(...) {}
       template<typename T> Logger& operator<<(T const&) { return *this;}
    };
     
    template<> struct Logger<false> {
       Logger(...) {}
       ~Logger() { std::cerr << str_.str() << std::endl; }
       template<typename T> Logger& operator<<(T const&t) { str_ << t; return *this; }
    private:
       std::stringstream str_;
    };
     
    enum Severity { debug, log, warning, error};
    #define Log(a, b) Logger<b==debug>(a, b)
    à complèter pour la gestion des __LINE__, __FILE__ etc...

  7. #7
    Membre éclairé
    Inscrit en
    Octobre 2004
    Messages
    616
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 616
    Par défaut
    Je suis un peu à l'ouest et j'ai du mal a avoir une vison clair des choses ( mon niveau de débutant en matière de template n'aidant pas .. ), enfin bref, voilà ce que je pense :

    Tu proposes de templatiser carrément la classe Logger . Hum, ca veux dire, créer un objet "Log" a chaque apelle d'un log, je sais pas, ca ne me parait pas propre et assez lourd ...c'est peut-etre pas le cas, mais c'est juste une impression

    De plus si je me trompes pas, ca ne règle pas mon problème, en effet, ca ne fait que "ne rien logger", mais l'objet "log" est créer, il se renvoie du *this à tour de bras ect.... moi ce que je veux c'est la disparition pure et simple du code et de tout appel de fonction lorsque je le spécifie en début de programme .

    Enfin, la on à deux template, il va m'en faloir X^( nbre de type de log possible) , pour généré toute les combinaisons ... ( bon là je m'emballe un peu surement, mais ce n'est pas le plus important )

    Le système en

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define Log(p) if(p=="WARNING" || p =="ERROR") std::cout << p << std::endl ;
    N'est-il pas préférable? ( bien que cela ne me convienne toujours pas )


    Note : il est tout a fait possible que j'ai totalement mal comprit ton code et que mon raisonnement soit archi-faux .... tu as le droit de me "basher" si c'est le cas !

  8. #8
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Tu proposes de templatiser carrément la classe Logger . Hum, ca veux dire, créer un objet "Log" a chaque apelle d'un log, je sais pas, ca ne me parait pas propre et assez lourd ...c'est peut-etre pas le cas, mais c'est juste une impression
    En général lorsqu'on est en train de logger un message, on ne recherche pas la performance maximale.
    Rien ne t'empêche de modifier le code de Jean-Marc pour utiliser la même instance à chaque appel.

    De plus si je me trompes pas, ca ne règle pas mon problème, en effet, ca ne fait que "ne rien logger", mais l'objet "log" est créer, il se renvoie du *this à tour de bras ect.... moi ce que je veux c'est la disparition pure et simple du code et de tout appel de fonction lorsque je le spécifie en début de programme .
    Comme te l'a dit Jean-Marc, tu ne peux pas virer le code sans l'aide du compilo, qui va (s'il n'est pas trop bête) virer complétement les fonctions vides.

    N'est-il pas préférable?
    Là tu ne vires aucun code à la compilation

    Note : il est tout a fait possible que j'ai totalement mal comprit ton code et que mon raisonnement soit archi-faux .... tu as le droit de me "basher" si c'est le cas !
    En tant que modérateur je m'octroie ce droit


  9. #9
    Membre éclairé
    Inscrit en
    Octobre 2004
    Messages
    616
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 616
    Par défaut
    Merci des réponses :

    En général lorsqu'on est en train de logger un message, on ne recherche pas la performance maximale.
    Tout à fait d'accord, quand je log, je m'en fou . Mais quand je ne log pas, je ne veux aucun "overhead" .

    Rien ne t'empêche de modifier le code de Jean-Marc pour utiliser la même instance à chaque appel.
    Je prend note

    Citation:
    N'est-il pas préférable?

    Là tu ne vires aucun code à la compilation
    Je l'aisse un "if" et lui un chainage de *this ... bref n'étant pas un compilateur, je ne m'engagerai pas sur le plus performant ... mais bon a la limite, c'est pareil, c'est pas joli :p

    En tant que modérateur je m'octroie ce droit
    Warf .... un jour je serai modo


    En fait, le truc c'est que ca marche super bien sans les flux, mais je déteste ( je suis alergique ) a la syntaxe C type printf()

    Log_Warning("ma syntaxe bizzare avec des %d %f ect....")

    et aprés il suffit d'un truc du genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    #define WARNING 1
    #if WARNING == 1
    #define Log_Warning(t) cLogger::Get().write(t,__FILE__,__LINE__)
    #if WARNING == 0
    #define Log_Warning(t)
    #endif
    Mais avec les flux .... *ouch*

  10. #10
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Clad3
    Tu proposes de templatiser carrément la classe Logger . Hum, ca veux dire, créer un objet "Log" a chaque apelle d'un log, je sais pas, ca ne me parait pas propre et assez lourd ...c'est peut-etre pas le cas, mais c'est juste une impression
    Lourd par rapport à quoi? Plus léger que Logger<true> comme objet, j'ai du mal à imaginer.

    De plus si je me trompes pas, ca ne règle pas mon problème, en effet, ca ne fait que "ne rien logger", mais l'objet "log" est créer, il se renvoie du *this à tour de bras ect.... moi ce que je veux c'est la disparition pure et simple du code et de tout appel de fonction lorsque je le spécifie en début de programme.
    Il y a de très bonne chance que mon Logger<true> ait exactement cet effet. En fait, s'il ne l'a pas et que les perfs sont réellement importantes, changer de compilateur me semble une bonne première étape.

    Enfin, la on à deux template, il va m'en faloir X^( nbre de type de log possible) , pour généré toute les combinaisons ... ( bon là je m'emballe un peu surement, mais ce n'est pas le plus important )
    Ca ne me semble pas nécessaire.

    Le système en

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define Log(p) if(p=="WARNING" || p =="ERROR") std::cout << p << std::endl ;
    N'est-il pas préférable? ( bien que cela ne me convienne toujours pas )
    Premièrement, tu changes complètement l'interface de ton premier message qui demandait de pouvoir faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Log(FILE|CONSOLE,WARNING) << "Ma variable i vaux : " << i << "\n" ;
    ce que mon système permet. Et la création d'un objet temporaire est le seul moyen qu'une telle expression forme un message complet (on peut changer légèrement l'interface et dire que le message se termine au flush et donc faire utiliser std::endl ou même un manipulateur créé exprès pour cet office)

    Deuxièmement, ton p=="WARNING" n'a vraissemblablement pas l'effet voulu (on compare des pointeurs).

    Troisièmement, ce n'est pas comme ça qu'on écrit des macros avec des if dedans.

    Mais oui, quelque chose du genre a des chances de ne pas entraîner de génération de code. Tout comme ma méthode.

  11. #11
    Membre éclairé
    Inscrit en
    Octobre 2004
    Messages
    616
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 616
    Par défaut
    Merci, je vais réfléchir un peu à tout ca de mon côté de relire bien toute les solutions que vous m'avez proposé Ca va me permettre d'avancer !

  12. #12
    Membre éclairé
    Inscrit en
    Octobre 2004
    Messages
    616
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 616
    Par défaut
    Juste une petite question, je n'ai jamais rencontré cette syntaxe avant, et j'ai du mal a trouver sur le web des info dessus ( étant donné que j'ignore comment s'apelle cette facons de procéder )

    Je parle d'une déclaration d'un variable sans la nommée:

    [ car si j'ai bien suivit, dans ton morceau de code Jean-Marc.Bourguet, tu procède ainsi en gros ]

    Logger() << ....

    J'ai testé, ca compile ce genre de chose, mais heu ...ca se passe comment ? la variable n'a pas de nom et est détruite en fin de portée normalement ? C'est standard ?
    Merci

  13. #13
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Juste une petite question, je n'ai jamais rencontré cette syntaxe avant, et j'ai du mal a trouver sur le web des info dessus ( étant donné que j'ignore comment s'apelle cette facons de procéder )

    Je parle d'une déclaration d'un variable sans la nommée:
    En général on parle de temporaire non nommé
    Tu en manipules plus souvent que tu ne le croies : par exemple dans "a = b + c", "b + c" produit un temporaire non nommé qui est ensuite affecté à "a" et détruit aussitôt.

    J'ai testé, ca compile ce genre de chose, mais heu ...ca se passe comment ? la variable n'a pas de nom et est détruite en fin de portée normalement ? C'est standard ?
    Oui c'est tout à fait standard (ce n'est qu'un appel à un constructeur -- ce qui va donc en toute logique construire une instance), et la portée de la variable est normalement celle de l'instruction courante, càd qu'elle sera détruite avant de passer à la ligne de code suivante.

  14. #14
    Membre éclairé
    Inscrit en
    Octobre 2004
    Messages
    616
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 616
    Par défaut
    Merci à tous, j'ai étalbie une première version de test, histoire de voir comment ca fonctionne, els premiers résultats sont concluants

    Voici le code ( tout est pour le moment dans mon main.cpp ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    #include <SDL/SDL.h>
    #include <iostream>
    #include <sstream>
    #include <string>
     
    #define WARNING 1
    #define ERROR 0
    #define MISC 0
     
    #define FILE     ((unsigned char) 0x01)
    #define SCREEN   ((unsigned char) 0x02)
    #define CONSOLE  ((unsigned char) 0x04)
    #define ALL      FILE | SCREEN | CONSOLE 
     
     
    #define Log(flag,type)  Logger<type == 1>(flag,__FILE__,__FUNCTION__,__LINE__)
     
    template<bool DoLog> class Logger;
     
    template <>
    class Logger<true>
    {
    public :
    	Logger(unsigned char Flag,const char * File, const char * Function,int Line)
    		: flag_(Flag),
    		 File_(File),
    		 Function_(Function),
    		 Line_(Line){}
    	~Logger()
    	{
    		std::stringstream Info ;
    		Info << "Log dans le fichier " << File_ << " dans la fonction " << Function_ <<
    			" à la ligne " << Line_  << ". Le message est de type : ";
    		if ( flag_ & FILE )
    			std::cout << Info.str() << "FILE : " << str_.str() << std::endl ;
    		if ( flag_ & SCREEN )
    			std::cout << Info.str() << "SCREEN : " << str_.str() << std::endl ;
    		if ( flag_ & CONSOLE )
    			std::cout << Info.str() << "CONSOLE : " << str_.str() << std::endl ;
    	}
    	template<typename T> Logger& operator<<(T const & t) { str_ << t; return * this; }
    private:
       std::stringstream str_;
       unsigned char flag_ ;
       const char * File_ ;
       const char * Function_ ;
       int Line_ ;
    };
     
    template <>
    class Logger<false>
    {
    public :
    	Logger(unsigned char Flag,const char * File, const char * Function,int Line){}
    	~Logger(){}
    	template<typename T> Logger& operator<<(T const & t) { return * this; }
    };
    Le main en question :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int main(int argc, char *argv[])
    {
    	SDL_Init(0);
    	int i = 12 ;
    	Log(ALL,WARNING) << " Warning Yay " << i ;
    	Log(FILE|SCREEN,ERROR) << " Error Yay" << i;
    	Log(CONSOLE|SCREEN,MISC) << " Misc Yay " << i ;
     
    	SDL_Quit();
    	return 0;
    }
    L'output :
    Log dans le fichier c:\documents and settings\propriétaire\bureau\ey-lord\ey-lord.cpp dans la fonction SDL_main à la ligne 65. Le message est de type : FILE : Warning Yay 12
    Log dans le fichier c:\documents and settings\propriétaire\bureau\ey-lord\ey-lord.cpp dans la fonction SDL_main à la ligne 65. Le message est de type : SCREEN : Warning Yay 12
    Log dans le fichier c:\documents and settings\propriétaire\bureau\ey-lord\ey-lord.cpp dans la fonction SDL_main à la ligne 65. Le message est de type : CONSOLE : Warning Yay 12
    Le code est un peu bordelique car je n'ai pas encore coder ma classe, mais si d'ors et déja vous voyez des choses à améliorer ... je suis preneur de tout conseils / critiques . Sinon je posterais d'ici demain soir je pense une version plus propre de tout ca, de facons a obtenir votre avis .
    Merci encore !

  15. #15
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    La solution de Jean-Marc, demande que l'on sache à la compilation si on veut logger ou pas, ce qui peut être restrictif. Pour une solution à coût faible (mais pas nul) et configurable au run-time, ce qui est important c'est que quand on écrit

    La fonction f ne soit pas évaluée.

    Le mieux que j'ai trouvé pour ça est une macro macro qui ne fasse pas une instruction complète, genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define Log(enable, level) if (!enable) ; else logger(level)
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  16. #16
    Membre éclairé
    Inscrit en
    Octobre 2004
    Messages
    616
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 616
    Par défaut
    Je n'avais jamais pensé à ce genre d'apel . En fait je n'en ai jamais eu l'utilité jusqu'à présent ... hormis peut-etre lors d'u debuggage d'un nouveau morceau de code, mais dans ce cas, je supprimer ce genre de log une fois le code stable .

    Je vais attendre de voir comment je Log en général [ a priori, pas besoin de fonction , mais sait-on jamais ... ] et si je m'appercois que j'y fait souvent appel, je transformerai mon code en conséquence

    Merci de la remarque !

  17. #17
    Membre éclairé
    Inscrit en
    Octobre 2004
    Messages
    616
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 616
    Par défaut
    Je vient de m'appercevoir ...j'aurais du m'en douter, que la macro FILE était définit quelquepart dans la stl déja ... bref, j'ai du changer de nom .

    Je me demande comment me passer de certain define ( tel que ceux la : )

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    #define LOG_FILE      0x00000001
    #define LOG_SCREEN    0x00000002
    #define LOG_CONSOLE   0x00000004
    #define LOG_ALL      LOG_FILE | LOG_SCREEN | LOG_CONSOLE
    Tout en gardant quelquechose de simple a écrire . J'ai penser à une énum, mais j'ai du mal à comprendre le principe ... ca m'a pas l'air mieux qu'un define , je me trompe ?

    En fait j'aimerai définir mes flag avec le nom que je veux, qui oient accesible uniquement par cette classe [ dont ne générant pas de conflit avec les autres fichiers ] et en gardant une syntaxe du type ( FILE | SCREEN | ALL ... ).

    EDIT : Hum les enums ca ne m'a pas mener loin ... car pour eviter un probleme de conflit de nom, il faudrait que je les mette dans mes deux définition de mon template Logger. [ ca ce n'est pas un probleme ] . Mais la ou ca coince, c'est la syntaxe pour utiliser mes flag aprés ca : "Logger<true>::FILE" ... c'est pas trés sympatique ca !

  18. #18
    Membre éclairé
    Inscrit en
    Octobre 2004
    Messages
    616
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 616
    Par défaut
    Voilà ma classe , qui à bien avancé . Je suis sur qu'il y encore pas mal de choses à redire, et je vous fait confiance [même des détails, n'hésitez pas!]

    Je réfléchis sur un petit point, pour le moment, je "log" dans un fichier ... sans jamais effacé ce fichier ( même en début d'une nouvelle cession d'utilisation de mon programme ) . J'aimerai le faire, mais je cherche une manière élégante d'intégrer ca a ma classe . [ j'aimerai que ca se fasse automatiquement, sans appel a une fonction Init() , ShutDown() , et sans devoir refaire le design complet de ma classe ... ] Si vous avez des idées ..

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    // Class : Logger
    // > Doing < It's a tool to mainly help the debugging process . We can retrieve informations when we want, 
    // --------- where we want, and how we want. 
    // > Todo  < Define the exact output types.
    // --------- Maybe change the way the FileOutput works (it just adds to the end of the file each time we log)
    // --------- FileOutPut is temporary , till a final format is chosen (xml?)
    // > How   < Use the macro Log(Msg Type,Output Type) and the operator << .
    // --------- Enable or disable some log with the "Msg Type" Macro.
    // >>>>>>>>> Adrien LAMBERT - 2005 / 2006
     
    #ifndef LOGGER_HPP
    #define LOGGER_HPP
     
    	// Output Type (Flags)
    	#define LOG_FILE      0x00000001
    	#define LOG_SCREEN    0x00000002
    	#define LOG_CONSOLE   0x00000004
    	#define LOG_ALL      LOG_FILE | LOG_SCREEN | LOG_CONSOLE 
     
    	// Msg Type (1 = Log / 0 = Don't)
    	#define LOG_WARNING 1
    	#define LOG_ERROR 1
    	#define LOG_MISC 1
     
    	#define Log(flag,type)  Logger<type == 1>(flag,__FILE__,__FUNCTION__,__LINE__)
     
    	// Standard includes
    	#include <sstream>
    	#include <iostream>
    	#include <fstream>
     
    	// Template, general declaration
    	template<bool DoLog> class Logger;
     
    	// Template version, if we actually want to log something .
    	template<> class Logger<true>
    	{
    	public :
     
    		Logger(unsigned char Flag,const char * File, const char * Function,int Line)
    			: Flag_(Flag),
    			File_(File),
    			Function_(Function),
    			Line_(Line),
    			FileName_("Log.txt")
    		{
    		}
     
    		~Logger()
    		{
    			if ( Flag_ & LOG_FILE )
    			{
    				std::ofstream FileStream(FileName_,std::ios_base::app); 
    				FileStream << Msg_.str() ;
    			}
    			if ( Flag_ & LOG_SCREEN )	
    				{ /* TODO */ }
    			if ( Flag_ & LOG_CONSOLE )
    				{ /* TODO */ }
    		}
    		template<typename T> Logger & operator << (T const & t) { Msg_ << t; return * this; }
     
    	private:
    		// Data
    		std::stringstream Msg_;
    		unsigned char Flag_ ;
    		const char * File_ ;
    		const char * Function_ ;
    		int Line_ ;
    		const char * FileName_; 
    	};
     
    	// Template version, if we do NOT want to log .
    	template<> class Logger<false>
    	{
    	public :
     
    		Logger(unsigned char Flag,const char * File, const char * Function,int Line){}
     
    		~Logger(){}
     
    		template<typename T> Logger& operator<<(T const & t) { return * this; }
     
    	};
     
    #endif // LOGGER_HPP
    Edit : Désolé pour l'anglais aproximatif .

  19. #19
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Je réfléchis sur un petit point, pour le moment, je "log" dans un fichier ... sans jamais effacé ce fichier ( même en début d'une nouvelle cession d'utilisation de mon programme ) . J'aimerai le faire, mais je cherche une manière élégante d'intégrer ca a ma classe . [ j'aimerai que ca se fasse automatiquement, sans appel a une fonction Init() , ShutDown() , et sans devoir refaire le design complet de ma classe ... ] Si vous avez des idées ..
    Faire de FileStream une donnée membre statique ?

  20. #20
    Membre éclairé
    Inscrit en
    Octobre 2004
    Messages
    616
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 616
    Par défaut
    En effet cela a suffit
    J'ai également rajouté un std::flush, aprés chaque message , comme ca je récupère mes données aprés chaque log et non pas en fin de programme ...

    Maintenant je suis entrain de voir comment exporter ca en xml ... je pense qu'il va me faloir cette fois-ci passé par des fonction init() et shutdown() :/
    Enfin je vais voir

Discussions similaires

  1. [Servlet][Deb]envoyer image gif sur le flux http
    Par ptitBoutchou dans le forum Servlets/JSP
    Réponses: 15
    Dernier message: 09/04/2004, 10h12
  2. Acquerir un flux audio
    Par The Cyber Lewis dans le forum DirectX
    Réponses: 1
    Dernier message: 05/04/2004, 14h13
  3. Rediriger un flux de données sous linux
    Par Nicaisse dans le forum POSIX
    Réponses: 7
    Dernier message: 01/07/2003, 16h04
  4. Copie d'un flux dans un autre
    Par Morvan Mikael dans le forum Langage
    Réponses: 5
    Dernier message: 03/06/2003, 09h40
  5. [reseaux] redirection de flux
    Par Olive1808 dans le forum Programmation et administration système
    Réponses: 2
    Dernier message: 12/08/2002, 09h24

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo