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 :

Comment simplifier l'écriture de mon code à l'aide d'une macro ?


Sujet :

Langage C++

  1. #1
    Invité
    Invité(e)
    Par défaut Comment simplifier l'écriture de mon code à l'aide d'une macro ?
    Salut.

    j'essaye de simplifier mon système de sérialisation d'objet, avec le polymorphisme je devais en effet déclarer une classe de base qui prenait un template ce qui était plutôt gênant lorsque je voulais stocker mes objets dans un conteneur et les sérialiser car après je devais rechercher le type et faire un cast.

    De plus comme la fonction serialize prend un paramètre template je ne peut pas faire une interface, de plus ce paramètre template possède des fonctions qui sont elle même template donc je ne peux pas faire de classe de base non plus.

    L'idée est de faire une classe de base contenant, tout les type des classes dérivée à l'aide d'un template variadique, et de rechercher le bon type à l'aide d'un tuple, comme ceci :

    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
     
    #ifndef ODFAEG_SERIALIZATION
    #define ODFAEG_SERIALIZATION
    #include "archive.h"
    #include <iostream>
    #include <typeinfo>
    #include "tuple.h"
    #include <tuple>
    namespace odfaeg {
    template <class B, class... D>
    class Serializer {
        public :
        Serializer (D... derived) {
            derivedClasses = std::forward_as_tuple(derived...);
            baseObject = nullptr;
        }
        Serializer(B* baseObject, D... derived) : baseObject(baseObject) {
            derivedClasses = std::forward_as_tuple(derived...);
        }
        template <typename Archive>
        void checkType(Archive & ar) {
            serialize(derivedClasses, ar);
        }
        template<int... S, typename Archive>
        void serialize (std::tuple<D...> types, Archive & ar) {
            //The class doesn't inherits;
            if (sizeof...(D) == 0 && baseObject != nullptr) {
                baseObject->serialize(ar);
            //The base class is abstract and have derived classes. (We must check the type of the derived object at runtime.
            } else if (sizeof...(D) > 0 && baseObject == nullptr) {
                serialize(typename helper::gens<sizeof...(D)>::type(), types, ar);
            //The base class isn't abstract and have derived classes.
            } else if (sizeof...(D) > 0 && baseObject != nullptr) {
                if(!serialize(typename helper::gens<sizeof...(D)>::type(), types, ar))
                    baseObject->serialize(ar);
            }
        }
        template<int... S, typename Archive>
        bool serialize(helper::seq<S...>, std::tuple<D...> params, Archive & ar)
        {
            if (evaluateType(std::get<S>(params)..., ar)) {
                return true;
            }
            return false;
        }
        template <typename T, typename Archive>
        bool evaluateType (T type, Archive & ar) {
            if (typeid(type) == typeid(*baseObject)) {
                type.serialize(ar);
                return true;
            }
        }
        virtual void onSave() {
        }
        virtual void onLoad() {
        }
        B* baseObject;
        std::tuple<D...> derivedClasses;
    };
    }
    #endif // SERIALIZATION

    Malheureusement ceci n'améliore pas vraiment mon problème, je ne peux pas faire hérité ObjetToutBete de Serializer<ObjetToutBete, ObjetContenantObjetToutBete> car, la classe Serializer à besoin de la définition complète de la classe ObjetContenantObjetToutBete, et même chose dans l'autre sens, la classe ObjetContenantObjetToutBete à besoin de la définition complète de la classe ObjetToutBete de ce fait je ne peux pas non plus déclarer la classe ObjetContenantObjetToutBete avant la classe ObjetToutBete.

    J'ai du donc créer un troisième classe que voici, celle-ci contient juste le type réel de l'objet, ainsi que les types dérivé, et l'objet à sérializer.

    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
     
    class ObjetToutBete  {
    public :
        ObjetToutBete() {}
        ObjetToutBete(std::string name) {
            this->name = name;
            id = new int(5);
        }
        template <typename Archive>
        void serialize(Archive & ar) {
            ar(name);
            ar(id);
        }
        int* getId() {
            return id;
        }
        //Pour que typeid marche!!!
        virtual void foo() {}
    private :
        std::string name;
        int* id;
    };
    class ObjetContenantObjetToutBete : public ObjetToutBete {
    public :
        ObjetContenantObjetToutBete () {}
        ObjetContenantObjetToutBete(std::string name) : ObjetToutBete("un objet tout bête.") {
            this->name = name;
            id = ObjetToutBete::getId();
        }
        template <typename Archive>
        void serialize(Archive & ar) {
            ObjetToutBete::serialize(ar);
            ar(name);
            ar(id);
        }
    private :
        int* id;
        std::string name;
    };
    class SerializableObject : public odfaeg::Serializer<ObjetToutBete, ObjetContenantObjetToutBete> {
    public :
        SerializableObject(ObjetToutBete* objet) : Serializer<ObjetToutBete, ObjetContenantObjetToutBete>(objet, static_cast<ObjetContenantObjetToutBete&>(*objet)) {
        }
    };

    L'inconvénient est que je dois créer un nouvelle classe pour chacune des classes de base qui ont des classes dérivée ce qui est un peu lourd;

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    ObjetToutBete* ocotb = new ObjetContenantObjetToutBete("Objet contenant objet tout bête.");
    SerializableObject so(ocotb);

    Et j'aimerais pouvoir simplifier tout ça à l'aide d'une macro afin qu'il ne soit plus nécessaire de créer manuellement la classe supplémentaire.

    Voilà merci de votre aide.

  2. #2
    Invité
    Invité(e)
    Par défaut
    J'ai essayé ceci :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    #define SERIALIZE(OBJECT, ARCHIVE, ...) odfaeg::Serializer<__VA_ARGS__> s (static_cast<__VA_ARGS__>(OBJECT)...); \
                                                  ARCHIVE<<s;
     
    SERIALIZE(ocotb, oa, ObjetToutBete, ObjetContenantObjetToutBete);

    Mais ça ne fonctionne pas. :/

    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
     
    ||=== Build: Debug in ODFAEG-DEMO (compiler: GNU GCC Compiler) ===|
    /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|11|warning: __VA_ARGS__ can only appear in the expansion of a C99 variadic macro [enabled by default]|
    /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|11|warning: __VA_ARGS__ can only appear in the expansion of a C99 variadic macro [enabled by default]|
    /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp||In function ‘int main(int, char**)’:|
    /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|90|error: expected ‘>’ before ‘,’ token|
    /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|9|note: in definition of macro ‘SERIALIZE’|
    /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|90|error: expected ‘(’ before ‘,’ token|
    /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|9|note: in definition of macro ‘SERIALIZE’|
    /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|90|error: expected primary-expression before ‘,’ token|
    /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|9|note: in definition of macro ‘SERIALIZE’|
    /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|9|error: expected primary-expression before ‘>’ token|
    /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|90|note: in expansion of macro ‘SERIALIZE’|
    /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|9|error: expected ‘)’ before ‘...’ token|
    /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|90|note: in expansion of macro ‘SERIALIZE’|
    /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|96|error: ‘so’ was not declared in this scope|
    ||=== Build failed: 6 error(s), 2 warning(s) (0 minute(s), 2 second(s)) ===|
    Pourquoi ?

  3. #3
    Invité
    Invité(e)
    Par défaut
    Impeccable j'ai réussi!

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    #define SERIALIZE(object, archive, TYPE, TYPES...) odfaeg::Serializer<TYPE, TYPES> s(object, dynamic_cast<TYPE*>(object)); \
                                                            archive<<s
    #define DESERIALIZE(object, archive, TYPE, TYPES...) odfaeg::Serializer<TYPE, TYPES> s(object, dynamic_cast<TYPE*>(object)); \
                                                            archive>>s

    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
     
     ObjetToutBete* ocotb = new ObjetContenantObjetToutBete("Objet contenant objet tout bête.");
        std::ofstream ofs("FichierDeSerialisation");
        {
            odfaeg::OTextArchive oa(ofs);
            SERIALIZE(ocotb, oa, ObjetToutBete, ObjetContenantObjetToutBete);
     
        }
        ofs.close();
        std::ifstream ifs("FichierDeSerialisation");
        {
            odfaeg::ITextArchive ia(ifs);
            DESERIALIZE(ocotb, ia, ObjetToutBete, ObjetContenantObjetToutBete);
        }
        ifs.close();
        return 0;

    Suffise que je passe l'objet à sérializer, l'archive, le type réel de l'objet à sérializer et les types des objets dérivé (si il y en a) à la macro et voilà.

    Pratique quand même les macros, maintenant je ne sais pas si c'est al meilleure solution. ^^

  4. #4
    Membre émérite
    Avatar de skeud
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2011
    Messages
    1 091
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 1 091
    Points : 2 724
    Points
    2 724
    Billets dans le blog
    1
    Par défaut
    Oubli pas le tag résolu .

    [HS]encore un coup de magicien de la part de dvp.com, pas de réponse mais une solution quand même ^^[/HS]
    Pas de solution, pas de probleme

    Une réponse utile (ou +1) ->
    Une réponse inutile ou pas d'accord -> et expliquer pourquoi
    Une réponse à votre question


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

Discussions similaires

  1. [XL-2007] comment faire pr mettre a mon code les jours de la semaine sans le week end
    Par alexandrek dans le forum Macros et VBA Excel
    Réponses: 9
    Dernier message: 09/02/2011, 22h53
  2. Comment appeler un fichier dans mon code
    Par olfasupcom dans le forum Langage
    Réponses: 5
    Dernier message: 30/05/2007, 12h16
  3. Comment visualiser le resultat de mon code
    Par Blaireau dans le forum Langage
    Réponses: 3
    Dernier message: 13/08/2006, 20h31
  4. Serveur/Client UDP: comment envoyer un fichier avec mon code
    Par danje dans le forum Entrée/Sortie
    Réponses: 7
    Dernier message: 21/12/2005, 14h54

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