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

Langage C++ Discussion :

Tester si une methode de classe existe KO avec classe template


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Profil pro
    System Integration Project Manager
    Inscrit en
    Octobre 2006
    Messages
    219
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : System Integration Project Manager
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2006
    Messages : 219
    Par défaut Tester si une methode de classe existe KO avec classe template
    Bonjour a tous,

    je dois developper une solution qui imite certains points de boost::serialization (car je ne peux utiliser boost dans mon projet).

    Ce que je cherche a imiter, c'est le fait qu'une classe peut etre serialisée soit par une methode, soit par une 'free function'.

    en googlant, j'ai trouvé ce post tres interessant qui m'a permis de jeter les bases d'une solution.

    Toutefois, je rencontre un pb. J'ai ecrit la classe template "Serializer" (cf ci-dessous)
    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
    template <class OBJECT>
    class Serializer
    {
    public: 
    	typedef OBJECT ObjectType;
     
    	Serializer(ObjectType *p_pObject) : m_pObject(p_pObject) 
    	{	};
     
    	virtual ~Serializer() 
    	{	};
     
    	std::string Serialize()
    	{
    		std::string l_str;
    		if (m_pObject) {
    			if (Utils::has_serialize_member<OBJECT,void (OBJECT::*)(std::string &, const unsigned int)>::value)
    				m_pObject->serialize(l_str,0);
    			else 
    				serialize(l_str,*m_pObject,0);
    		}
    		return l_str;
    	};
     
    private :
    	ObjectType *m_pObject;
    };
    dont la méthode fait le travail (utilisation de la méthode 'serialise' de la classe de l'objet ou de la fonction 'serialize').

    C'est dans cette fonction que ca coince : Utils::has_serialize_member<OBJECT,void (OBJECT::*)(std::string &, const unsigned int)>::value vaut toujours 'faux' donc le compilo cherche une fonction serialize(std::string &, OBJECT &, const unsigned int) qu'il ne trouve pas ...

    Ce qui est bizarre, c'est que si j'appelle Utils::has_serialize_member<TestObject,void (TestObject::*)(std::string &, const unsigned int)>::value
    avec TestObject =
    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
    	class TestObject 
    	{
    	public:
    		TestObject () {m_Data=0.;};
    		virtual ~TestObject () {};
     
    		void serialize(std::string& ar, const unsigned int version)
    		{
    			std::stringstream l_SS;
    			l_SS<<"TestObject ::serialize - Data = ["<<m_Data<<"]";
    			ar = l_SS.str();
    		};
     
    		//! public for testing
    		double m_Data;
    	};
    ca marche parfaitement.

    On dirait que le compilo est perdu a cause du template "OBJECT".

    Quelqu'un a-t-il deja rencontré ce pb ou a une idée sur le pb et sur une solution eventuelle ?

    Merci

    V

  2. #2
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Est-ce que tu pourrais montrer le code de has_serialize_member ?

    Ca nous permettrais peut-être de trouver un problème (parce que là...).

    De manière générale, on préférera éviter le if(trait<T>::value) pour utiliser une classe de politique :

    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
     
    template <class T, bool B = utils::has_serialize_member<T, void (T::*)(std::string &, const unsigned int)>::value>
    struct serializer_helper;
     
    template <class T>
    struct serializer_helper<T, false>
    {
      void do_serialize(std::string& lstr, T *o)
      {
        serialize(lstr, *o, 0);
      }
    };
     
    template <class T>
    struct serializer_helper<T, true>
    {
      void do_serialize(std::string& lstr, T *o)
      {
        o->serialize(lstr, 0);
      }
    };
     
    template <class OBJECT>
    class Serializer
    {
    public:
      std::string Serialize()
      {
        std::string l_str;
        if (m_pObject) {
            serialize_helper<T>::do_serialize(l_str, m_pObject);
        }
        return l_str;
      }
    };
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  3. #3
    Membre éclairé
    Profil pro
    System Integration Project Manager
    Inscrit en
    Octobre 2006
    Messages
    219
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : System Integration Project Manager
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2006
    Messages : 219
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Est-ce que tu pourrais montrer le code de has_serialize_member ?

    Ca nous permettrais peut-être de trouver un problème (parce que là...).
    bien sur
    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
    namespace Utils
    {
    template<class T, class Func> struct has_serialize_member
    {
    private:
       struct true_t {};
       struct false_t {true_t t[2];};
     
     
       template<typename T2, Func f> struct has_member;
       template<class T2>
       static true_t test(has_member<T2,&T2::serialize>*);
       template<class T2>
       static false_t test(...);
    public:
       static const bool value = (sizeof(test<T>(0))==sizeof(true_t));
    };
    };
    Citation Envoyé par Emmanuel Deloget Voir le message
    De manière générale, on préférera éviter le if(trait<T>::value) pour utiliser une classe de politique :

    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
     
    template <class T, bool B = utils::has_serialize_member<T, void (T::*)(std::string &, const unsigned int)>::value>
    struct serializer_helper;
     
    template <class T>
    struct serializer_helper<T, false>
    {
      void do_serialize(std::string& lstr, T *o)
      {
        serialize(lstr, *o, 0);
      }
    };
     
    template <class T>
    struct serializer_helper<T, true>
    {
      void do_serialize(std::string& lstr, T *o)
      {
        o->serialize(lstr, 0);
      }
    };
     
    template <class OBJECT>
    class Serializer
    {
    public:
      std::string Serialize()
      {
        std::string l_str;
        if (m_pObject) {
            serialize_helper<T>::do_serialize(l_str, m_pObject);
        }
        return l_str;
      }
    };
    je crois que vous avez mis le doigt dessus! je mixe du compile-time et du runtime avec le if et maintenant que vous me le faites remarquer, c'est pas bien...

    Je regarde vos prop et je reviens si besoin (ou pour tagger 'resolu'...)

    merci

    V

  4. #4
    Membre éclairé
    Profil pro
    System Integration Project Manager
    Inscrit en
    Octobre 2006
    Messages
    219
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : System Integration Project Manager
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2006
    Messages : 219
    Par défaut
    hey les gars, vous etes des gurus, je vous venere !!
    la solution de koala01, copié/collé a presque fonctionné directement !

    merci !!

  5. #5
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par vdaanen Voir le message
    hey les gars, vous etes des gurus, je vous venere !!
    la solution de koala01, copié/collé a presque fonctionné directement !

    merci !!
    Laquelle ? parce que j'en ai proposé trois (dont une sur laquelle Emmanuel m'a grillé )
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #6
    Membre éclairé
    Profil pro
    System Integration Project Manager
    Inscrit en
    Octobre 2006
    Messages
    219
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : System Integration Project Manager
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2006
    Messages : 219
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Laquelle ? parce que j'en ai proposé trois (dont une sur laquelle Emmanuel m'a grillé )
    Slt
    La derniere (le code non testé) fonctionne parfaitement

  7. #7
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Est-ce que tu pourrais montrer le code de has_serialize_member ?

    Ca nous permettrais peut-être de trouver un problème (parce que là...).

    De manière générale, on préférera éviter le if(trait<T>::value) pour utiliser une classe de politique :

    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
     
    template <class T, bool B = utils::has_serialize_member<T, void (T::*)(std::string &, const unsigned int)>::value>
    struct serializer_helper;
     
    template <class T>
    struct serializer_helper<T, false>
    {
      void do_serialize(std::string& lstr, T *o)
      {
        serialize(lstr, *o, 0);
      }
    };
     
    template <class T>
    struct serializer_helper<T, true>
    {
      void do_serialize(std::string& lstr, T *o)
      {
        o->serialize(lstr, 0);
      }
    };
     
    template <class OBJECT>
    class Serializer
    {
    public:
      std::string Serialize()
      {
        std::string l_str;
        if (m_pObject) {
            serialize_helper<T>::do_serialize(l_str, m_pObject);
        }
        return l_str;
      }
    };
    N'aurais tu pas oublié un static quelque part, vu que tu appelle serialize_helper<T>::do_serialize
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  8. #8
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par koala01 Voir le message
    N'aurais tu pas oublié un static quelque part, vu que tu appelle serialize_helper<T>::do_serialize
    Voui, je confirme, c'est une erreur de mon coté. Le static est effectivement nécessaire
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  9. #9
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Voui, je confirme, c'est une erreur de mon coté. Le static est effectivement nécessaire
    Pour une fois que je peux reprendre du code que tu écris, fallait pas croire que j'allais laisser passer l'occasion
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  10. #10
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Ce qui se passe, surtout, c'est qu'un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if (condition ){
        /* ... */
    }else {
       /* ... */
    }
    ne pourra être évalué qu'à l'exécution, mais, pour cela, il faut que tout ce qui se trouve aussi bien dans la portée du if que dans la portée du else existe.

    Autrement dit, si tu as
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class MaClass{
        public:
        void serialize(std::string& ar, const unsigned int version);
    };
    (la fonction membre en somme ) mais pas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void serialize(void serialize(std::string& ar, MaClass & obj, const unsigned int version)
    (la fonction libre ), le compilateur sera content pour la partie "if", mais il t'enverras sur les roses pour la partie "else", et, dans l'autre sens, si tu as la fonction libre mais pas la fonction membre, il sera content pour la partie "else", mais pas pour la partie "if", et il t'enverra aussi sur les roses.

    Il faut donc trouver le moyen de faire en sorte que ce soit lors de la compilation que la décision de passer "d'un coté ou de l'autre" soit prise.

    L'une des possibilités "faciles à mettre en oeuvre" (mais assez lourde à lire) consiste à utiliser le test "ternaire", qui peut, lui, être évalué à la compilation (pour autant que la valeur testée puisse etre considérée comme une constante de compilation, ce qui est normalement le cas ici) sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    		if (m_pObject) {
    			(Utils::has_serialize_member<OBJECT,void (OBJECT::*)
                                    (std::string &, const unsigned int)>::value) ? //test
    				m_pObject->serialize(l_str,0) :  // si value ==true
    				serialize(l_str,*m_pObject,0) ); // si value == false
    		}
    Une alternative, si tu peux utiliser C++11, est d'utiliser "enable_if", sous une forme proche de
    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
    template <class OBJECT>
    class Serializer
    {
    public:
    std::string Serialize()
    	{
    		std::string l_str;
    		doSerialize(Utils::has_serialize_member<OBJECT,void (OBJECT::*)
                               (std::string &, const unsigned int)>::value);
    		return l_str;
    	};
    private: 
        void doSerialize(Utils::has_serialize_member<OBJECT,void (OBJECT::*)
                                 (std::string &, const unsigned int)>::value)
        {
            m_pObject->serialize(l_str,0);
        }
        void doSerialize(Utils::has_serialize_member<OBJECT,void (OBJECT::*)
                                (std::string &, const unsigned int)>::value==false)
        {
            serialize(l_str,*m_pObject,0); 
        }
    };
    (CODE NON TESTE !!!) ou, si tu ne dispose pas de C++1, tu peux aussi te rappeler que "tout problème en informatique peut être résolu par un niveau d'indirection supplémentaire, et créer un foncteur template proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    template <typename Object, bool memberFunction> //par défaut : pour memberFunction == true
    struct RealSerializer{
        void operator()(Object & obj, std::string & lstr) const{
            obj.serialize(lstr,0);
        }
    }
    template <typename Object> //spécifiquement: pour memberFunction == false
    struct RealSerializer<Object, false>{
        void operator()(Object & obj, std::string & lstr) const{
            serialize(obj, lstr,0);
        }
    }
    Dont tu pourrais, pour te faciliter la tache, définir un typedef dans ta classe
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Serializer sous la forme de
    template <typename Object>
    {
        typedef RealSerializer<Utils::has_serialize_member<OBJECT,void (OBJECT::*)
                                  (std::string &, const unsigned int)>::value> serializer_type;
    };
    et qui serait appelé, dans la fonction serialize, sous une forme proche de
    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
    template <class OBJECT>
    class Serializer
    {
    public: 
    	typedef OBJECT ObjectType;
     
    	Serializer(ObjectType *p_pObject) : m_pObject(p_pObject) 
    	{	};
     
    	virtual ~Serializer() 
    	{	};
     
    	std::string Serialize()
    	{
    		std::string l_str;
    		if (m_pObject) {
                        /* version avec le typedef */
                        serializer_type()(*m_pObject, l_str);
                        /* OU OU OU (version sans le typedef ) */
                        RealSerializer<Utils::has_serialize_member<OBJECT,void (OBJECT::*)
                                      (std::string &, const unsigned int)>::value>()(*m_pObject, l_str);
    		}
    		return l_str;
    	};
     
    private :
    	ObjectType *m_pObject;
    };
    (CODE NON TESTE!!!)

    Bienvenue dans le monde merveilleux de la programmation générique
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  11. #11
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Sinon, il y a toujours la solution de lire boost.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Développez une application Web dynamique et interactif avec des templates
    Par llaffont dans le forum Général Conception Web
    Réponses: 2
    Dernier message: 21/02/2011, 15h56
  2. Réponses: 0
    Dernier message: 05/04/2010, 11h47
  3. class not found avec class.forName
    Par gentil dans le forum Général Java
    Réponses: 1
    Dernier message: 18/03/2010, 15h02
  4. Réponses: 1
    Dernier message: 27/02/2009, 12h29
  5. Tester si une procedure stockee s'est terminee avec succes
    Par graphicsxp dans le forum MS SQL Server
    Réponses: 6
    Dernier message: 08/04/2005, 11h15

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