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 :

Petit problème avec une macro!


Sujet :

Langage C++

  1. #21
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    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 189
    Points : 17 141
    Points
    17 141
    Par défaut
    C'est bien ce que je craignais.

    A part que Base1 devient Base2, l'intégralité du contenu de Base1 et Base2 est identique.
    Du coup, tu pourrais profiter de deux paradigme qui semblent t'avoir échappés:

    L'héritage multiple et le CRTP (curiously recursing template pattern)

    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
    template <typename Base>
    struct Registered {
    	template<typename Archive>
    	void vtserialize(Archive & ar) {}
     
    	struct Key:
    	public odfaeg::Serializer<Base> {
    	public:
    		Key() : Serializer<Base>() {}
    		void register_object (Base* object) { setObject(object); }
     
    		Base* allocate_object(std::string typeName) { return sallocate(typeName); }
     
    		std::string getTypeName () { return odfaeg::Serializer<Base>::getTypeName(); }
     
    		template <typename Archive>
    		void serialize_object (std::string funcName, std::string funcArgs, Archive & ar) {
    			serialize(funcName, funcArgs, ar);
    		}
    	};
    public:
    	typedef Key KEYTYPE;
    	static Base* allocate (std::string typeName) {
    		static KEYTYPE aKey;
    		return aKey.allocate_object(typeName);
    	}
    };
     
    struct Base1 : public Registered<Base1> {}
    struct Base2 : public Registered<Base2> {}
    Ce qui, concrètement, dans le code utilisateur signifie uniquement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    struct Base1 : public Registered<Base1> {}
    struct Base2 : public Registered<Base2> {}
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  2. #22
    Invité
    Invité(e)
    Par défaut
    Ok, je vais essayer ça!

    Merci!

    (Mais quel problème que ça peut généré si le contenu des deux sous classes est identiques)

    Ils sont quand même dans 2 classes différentes même si leur contenu est identique.

    vtserialize doit appartenir à Base1 et Base2, pas dans Registered.

    Et la fonction vtserialize de la classe dérivée ne peut être enregistrée qu'une seule fois. (et pour ça il faut que le contenu soit identique)
    Et puis l'objet dérivé ne peut pas être à la fois un pointeur sur le type Base1 et Base2 donc, si il est de type base1 ça appelle les fonctions base1, sinon, celles dans base2.
    Dernière modification par Invité ; 10/09/2014 à 18h56.

  3. #23
    Invité
    Invité(e)
    Par défaut
    Voilà j'ai changé le code : après réflexion c'est mieux ainsi, ainsi, plus besoin de macro dans la classe de base :

    Code cpp : 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
     
    #ifndef SERIALIZATION_IMPL
    #define SERIALIZATION_IMPL
    #include "serialization.h"
    namespace odfaeg {
    template <typename Base>
    struct Registered {
    	struct Key:
    	public Serializer<Base> {
    	public:
    		Key() : Serializer<Base>() {}
    		void register_object (Base* object) { Serializer<Base>::setObject(object); }
     
    		Base* allocate_object(std::string typeName) { return Serializer<Base>::sallocate(typeName); }
     
    		std::string getTypeName () { return Serializer<Base>::getTypeName(); }
     
    		template <typename Archive>
    		void serialize_object (std::string funcName, std::string funcArgs, Archive & ar) {
    			Serializer<Base>::serialize(funcName, funcArgs, ar);
    		}
    	};
    public:
    	typedef Key KEYTYPE;
    	static Base* allocate (std::string typeName) {
    		static KEYTYPE aKey;
    		return aKey.allocate_object(typeName);
    	}
    	Key key;
    };
    }
    #endif

    Juste besoin d'une macro dans le main et une autre à la fin du fichier.h de chaque classe dérivée car je ne peux pas enregistré de pointeur de fonction sur un constructeur.
    De plus j'ai besoin de la définition complète de la classe pour pouvoir alloué et ma librairie ne peux pas connaître la connaitre à l'avance vu que c'est l'utilisateur qui défini ses classes. (Pas la librairie)

  4. #24
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    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 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Tu n'as pas moyen de te passer des macros pour les déclarations des classes?

    Ne pourrais-tu pas passer par une classe utilitaire?
    Je pense au fonctionnement de std::vector, dont le second argument template est un allocator.

    La classe par défaut serait plus ou moins
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    template <typename T> struct creator {
        T* operator() {return new T();}
    }
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  5. #25
    Invité
    Invité(e)
    Par défaut
    Mmm, je vais essayer de tout faire avec une seule et même macro, je pense qu'il y a moyen,je vais essayer de déclarer un allocator dans le main avec la macro EXPORT_CLASS_GUID.

  6. #26
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    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 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Idéalement, il faudrait le donner en argument de la template Registered.
    Comme ca, il n'y aurait plus de macro du tout.

    Quitte à demander l'appel d'une unique fonction au cours du programme, à l'instar d'un srand() ou d'un SDL_init().
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  7. #27
    Invité
    Invité(e)
    Par défaut
    Voilà qui est fait!

    Code cpp : 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
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
     
    #ifndef ODFAEG_SERIALIZATION_HPP
    #define ODFAEG_SERIALIZATION_HPP
    #include <iostream>
    #include <sstream>
    #include <typeinfo>
    #include "tuple.h"
    #include <tuple>
    #include <map>
    #include "fastDelegate.h"
    #include "erreur.h"
    #include "archive.h"
     
    #define REGISTER_TYPE(ID, BASE, DERIVED) \
    { \
    DERIVED *derived##ID = nullptr; \
    odfaeg::Allocator<BASE> allocator##ID; \
    BASE*(odfaeg::Allocator<BASE>::*f##ID)(DERIVED*) = &odfaeg::Allocator<BASE>::allocate<DERIVED>; \
    odfaeg::FastDelegate<BASE*> allocatorDelegate##ID(f##ID, &allocator##ID, derived##ID); \
    odfaeg::BaseFact<BASE>::register_type(typeid(DERIVED).name(), allocatorDelegate##ID); \
    }
     
    #define REGISTER_FUNC(ID, funcName, SID, BASE, DERIVED, SIGNATURE, args...) \
    { \
    REGISTER_TYPE(ID, BASE, DERIVED) \
    void(DERIVED::*f##ID##funcName##SID)SIGNATURE = &DERIVED::vt##funcName; \
    odfaeg::FastDelegate<void> delegate##ID##funcName##SID (f##ID##funcName##SID, args); \
    odfaeg::BaseFact<BASE>::register_function(typeid(DERIVED).name(), #funcName, #SID, delegate##ID##funcName##SID); \
    }
     
    #define CALL_FUNC(BASE, funcName, SID, object, args...) \
    { \
    odfaeg::BaseFact<BASE>::callFunction(typeid(*object).name(), #funcName, #SID, object, args); \
    }
     
    #define EXPORT_CLASS_GUID(ID, BASE, DERIVED) \
    { \
    REGISTER_TYPE(ID, BASE, DERIVED) \
    std::ostringstream oss##ID; \
    std::istringstream iss##ID; \
    odfaeg::OTextArchive outa##ID(oss##ID); \
    odfaeg::ITextArchive ina##ID(iss##ID); \
    DERIVED* derived##ID = nullptr; \
    REGISTER_FUNC(ID, serialize, OTextArchive, BASE, DERIVED, (odfaeg::OTextArchive&), derived##ID, std::ref(outa##ID)) \
    REGISTER_FUNC(ID, serialize, ITextArchive, BASE, DERIVED, (odfaeg::ITextArchive&), derived##ID, std::ref(ina##ID)) \
    }
     
    namespace odfaeg {
    template <typename B>
    struct Allocator {
       template <typename D>
       B* allocate(D*) {
            return new D();
       }
    };
    template <typename B>
    class BaseFact {
        public :
        static void register_type(std::string typeName, FastDelegate<B*> allocatorDelegate) {
            typename std::map<std::string, FastDelegate<B*>>::iterator it = types.find(typeName);
            if (it == types.end()) {
                types[typeName] = allocatorDelegate;
            }
        }
        static void register_function(std::string typeName, std::string funcName, std::string funcArgs, FastDelegate<void> delegate) {
            typename std::map<std::string, FastDelegate<void>>::iterator it = functions.find(typeName+funcName+funcArgs);
            if (it == functions.end())
                functions[typeName+funcName+funcArgs] = delegate;
        }
        template <typename... A>
        static void callFunction(std::string typeName, std::string funcName, std::string funcArgs, A&&... args) {
            typename std::map<std::string, FastDelegate<void>>::iterator it = functions.find(typeName+funcName+funcArgs);
            if (it != functions.end()) {
                it->second.setParams(std::forward<A>(args)...);
                (it->second)();
            } else {
                throw Erreur(0, "Unregistred function exception!", 1);
            }
        }
        static B* create (std::string typeName) {
            typename std::map<std::string, FastDelegate<B*>>::iterator it = types.find(typeName);
            if (it != types.end()) {
                return (it->second)();
            }
            throw Erreur(0, "Unregistred type exception!", 1);
        }
        static std::string getTypeName (B* type) {
            typename std::map<std::string, FastDelegate<B*>>::iterator it = types.find(typeid(*type).name());
            if (it != types.end())
                return it->first;
        }
        private :
        static std::map<std::string, FastDelegate<B*>> types;
        static std::map<std::string, FastDelegate<void>> functions;
    };
    template <typename B>
    std::map<std::string, FastDelegate<B*>> BaseFact<B>::types = std::map<std::string, FastDelegate<B*>>();
    template <typename B>
    std::map<std::string, FastDelegate<void>> BaseFact<B>::functions = std::map<std::string, FastDelegate<void>>();
     
    template <class B>
    class Serializer : public BaseFact<B> {
        public :
        Serializer() : BaseFact<B>() {
            baseObject = nullptr;
        }
        void setObject(B* baseObject) {
            this->baseObject = baseObject;
        }
        template <typename Archive>
        void serialize(std::string funcName, std::string funcArgs, Archive & ar) {
            BaseFact<B>::callFunction(typeid(*baseObject).name(), funcName, funcArgs, baseObject, std::ref(ar));
        }
        B* sallocate(std::string typeName) {
            return BaseFact<B>::create(typeName);
        }
        std::string getTypeName() {
            return BaseFact<B>::getTypeName(baseObject);
        }
        private :
        B* baseObject;
    };
    }
    #endif // SERIALIZATION

    Ouais, il est vrai que je pourrais utiliser une fonction d'initialisation à la place de la macro EXPORT_CLASS_GUID.

    Mais bon ça ne change pas grand chose au niveau utilisation :

    Code cpp : 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
    87
    88
     
    #include<iostream>
    #include<string>
    #include <fstream>
    #include <functional>
    #include "odfaeg/Core/fastDelegate.h"
    #include "odfaeg/Core/serialization.impl"
    using namespace std::string_literals;
    using namespace std::placeholders;
    void foo(int i, int j)
    { std::cout << i << j; }
     
    struct E {
        E() {
            var = 10;
        }
        void foo(int i)
        { std::cout << i; }
        template <typename A>
        void serialize (A & ar) {
            ar(var);
        }
        int var;
    };
     
    struct B : public odfaeg::Registered<B> {
        B() {
            c = "serialize base";
        }
        virtual void foo()
        { std::cout << 1; }
        virtual void print() {
            std::cout<<c<<std::endl;
        }
        template <typename A>
        void vtserialize (A & ar) {
            ar(c);
        }
        virtual ~B();
        std::string c;
    };
     
    B::~B(){}
     
    struct C : B {
        C () {
            c = "serialize derived";
        }
        void foo() {
            std::cout << 2;
        }
        void print () {
            B::print();
            std::cout<<c<<std::endl;
        }
        template <typename A>
        void vtserialize (A & ar) {
            B::vtserialize(ar);
            ar(c);
        }
        std::string c;
    };
     
    struct D {
        void operator()(int i) const
        { std::cout << i; }
    };
     
    void bar(const std::string& s)
    { std::cout << s; }
     
    int goo(int i)
    { return i; }
    void foo (int *ri) {  std::cout<<*ri; }
    void foo (int& ri) {  std::cout<<ri; }
    int main(int argv, char* argc[]) {   
        EXPORT_CLASS_GUID(C, B, C)
        C c;
        B* b = &c;
        B* b2;
        std::ofstream ofs("FichierDeSerialisation");
        odfaeg::OTextArchive oa(ofs);
        oa(b);
        std::ifstream ifs("FichierDeSerialisation");
        odfaeg::ITextArchive ia(ifs);
        ia(b2);
        b2->print();
    }

    Une macro est peut être même mieux vu que là je ne dois pas passer de valeur, juste les types.
    Et c'est la classe de base qui sert d'identifiant pour la factory, je pense que je pourrai viré le 1er paramètre de la macro.

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Petit problème avec une DropDownList
    Par Dohmaker dans le forum VB.NET
    Réponses: 6
    Dernier message: 20/09/2007, 18h19
  2. Problème avec une macro faisant apel à un tableau Excell
    Par valouche dans le forum Macros et VBA Excel
    Réponses: 52
    Dernier message: 19/06/2007, 12h38
  3. Petit problème avec une procédure stockée
    Par Poulain dans le forum MS SQL Server
    Réponses: 1
    Dernier message: 18/05/2007, 18h58
  4. Petits problèmes avec une CListCtrl
    Par vanitom dans le forum MFC
    Réponses: 2
    Dernier message: 17/11/2005, 11h45
  5. (Petit ?) problème avec une page contenant du Flash
    Par ologram dans le forum Balisage (X)HTML et validation W3C
    Réponses: 2
    Dernier message: 01/09/2005, 18h45

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