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 :

Solution plus élégante possible ou pas ?


Sujet :

Langage C++

  1. #21
    Invité
    Invité(e)
    Par défaut
    J'ai essayé de sortir le dynamic_cast du serializer, et de le mettre dans l'archive mais j'ai alors des problèmes d'incomplete type avec les std::tuple_element. (Même en incluant les header des classes dérivée dans le fichier archive.h)


    Donc faut absolument que le tuple aie la définition complète des classes dérivée. :/

    Pas pratique. :/

  2. #22
    Membre chevronné Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 043
    Points : 2 234
    Points
    2 234
    Par défaut
    Non mais sérieusement revois ta logique sur la sérialisation. C'est d'un complexe sans nom. Un objet est responsable de sa propre lecture/écriture. Donc un objet qui doit être serialisable à des méthode read/write ou les opérateurs << et >>. Tu complexifie un problème qui peut se résoudre simplement. Tu ne fais que ajouter de la complexité sans rien apporter.
    Revois tout ça, sinon je te pari que dans 2 semaines tu y es encore.
    Homer J. Simpson


  3. #23
    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
    Sans blague, quand google donne un demi million de résultats (a priori) pour ostream zip, et que les premiers résultats sont des libs completes en quelques pages de code, je ne vois pas comment tu n'arrives pas à en faire autant.

    ton problème est divisible en trois partie:
    1. produire du binaire pour chaque type, et donner un nom unique à ce type.
      Il suffit alors d'hériter d'une classe telle que:
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      struct serializable {
          virtual std::string asBinary() const = 0;
          virtual std::string typename() const = 0;//please use fully qualified type name such as "std::string"
      };
      .
    2. créer un format quelconque enchainant identifiant de type et binaire correspondant.
      Sans compression, je coderai ca comme ceci:
      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
      namespace serializing{
      class Archive {
      private:
          multimap<std::string/*type_id*/, std::string /*serial form*/> data;
      public:
          Archive& operator <<(serializable const& that) {
              data.emplace(that.typename(), that.asBinary());
              return *this;
          }
          void toFile(const char* filename) {
              std::fstream file(filename);
              for(auto item : data) {
                  file<<item.first << item.second << '\n';
              }
          }
      };
      }


    Pour la deserialization, tu sais ce que tu veux obtenir, sinon, tu ne le demanderai pas. Utilise des factory et constructeur explicite depuis une string.
    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

  4. #24
    Invité
    Invité(e)
    Par défaut
    Pour la deserialization, tu sais ce que tu veux obtenir, sinon, tu ne le demanderai pas. Utilise des factory et constructeur explicite depuis une string.
    C'est plutôt au niveau de la désérialization que je sèche.

    Je ne vois pas comment allouer un pointeur sur un type, hors que je n'ai pas la définition complète de la classe pour ce type.

    Utiliser une factory tu me dis ?

    Ok, je vais essayer!

  5. #25
    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
    Pour désérialiser un objet précis, il faut que ta classe archive (de ta bibliothèque) donne (une copie de) la forme sérialisée de l'objet demandé.
    C'est au code utilisateur d'en faire ce qu'il veut.
    à lui d'écrire la fonction de conversion, de la même façon que c'était à lui de fournir la fonction de sérialisation.

    Quitte à passer par une spécialisation de template pour uniformiser un peu le code.

    Peut être quelque chose comme:
    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
    //archive.hpp
    #include <string>
    namespace serializing{
    struct undeserializable{}
    typedef std::string serial_form;
     
    class archive{
        private:
            serial_form sourceOf(id) const;
            template<typename T> T make<T>(serial_form serial) const {throw undeserializable();}
        public:
            template<typename T> get(id id) const {
                return make<T>(serialOf(id));
            }
     
    	// ...
    };
     
    }//serializing::

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    //camion.hpp
    #include "archive.hpp"
     
    class Camion{
        Camion(serializing::serial_form);
    };
    template<> Camion serializing::Archive::make<Camion>(serializing::serial_form serial) const {
        return Camion(serial);
    }

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    #include <iostream>
    #include "archive.hpp"
    #include "camion.hpp"
     
    using serializing::Archive;
    using namespace std;
    int main() {
        Archive archive;
        //probablement du code de chargement
        Camion monJoliCamion = archive.get<Camion>(17);
        cout << monJoliCamion<<endl;
        return 0;
    }
    Bien évidemment, il y aura au fond de la bibliothèque un fichier archive.cpp qui implémente la map<id, serializing::serial_form> que constitue Archive, ainsi que les accès fichiers correspondant.
    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

  6. #26
    Invité
    Invité(e)
    Par défaut
    Ok, bon, j'ai créer une factory pour enregistrer tout les types, ainsi que toutes les version des fonctions à appeler dans le main.

    Je me sert du type de base comme référence pour la factory.

    Et je prend comme id le type dynamique de l'objet pour appeler la bonne fonction.

    Premièrement donc j'ai du faire une factory, celle-ci permet d'enregister des fonctions et des types, je défini dans chaque classe dérivée une fonction pour aller un objet avec le type dynamique.

    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
     
    template <typename B>
    class BaseFact {
        public :
        static void register_type(std::string typeName, B*(*func)()) {
            typename std::map<std::string, B*(*)()>::iterator it = types.find(typeName);
            if (it == types.end())
                types[typeName] = func;
        }
        static void register_function(std::string typeName, FastDelegate<void> delegate) {
            typename std::map<std::string, FastDelegate<void>>::iterator it = functions.find(typeName);
            if (it == functions.end())
                functions[typeName] = delegate;
        }
        template <typename... A>
        static void callFunction(std::string typeName, A... args) {
            typename std::map<std::string, FastDelegate<void>>::iterator it = functions.find(typeName);
                if (it == functions.end()) {
                    it->second.setParams(args...);
                    (it->second)();
                }
        }
        static B* create (std::string typeName) {
            typename std::map<std::string, B*(*)()>::iterator it = types.find(typeName);
            if (it != types.end())
                return types[typeName]();
            return nullptr;
        }
        static std::string getTypeName (B* type) {
            typename std::map<std::string, B*(*)()>::iterator it = types.find(typeid(*type).name());
            if (it != types.end())
                return it->first;
        }
        private :
        static std::map<std::string, B*(*)()> types;
        static std::map<std::string, FastDelegate<void>> functions;
    };

    Ainsi je n'ai plus qu'à passer le type à l'exécution, et à créer l'objet, ou bien, appeler une fonction dessus, ça marche aussi pour les fonctions template à condition d'enregister chaque spécialisation possible pour la fonction template, l'utilité du delegate (contrairement à std::function) est que même si je ne connais pas le type dynamique de l'objet en compilation lors de l'appel de la fonction, je peux fournir un pointeur sur la fonction membre de la classe dérivée, le delegate va faire un down cast sur le type statique de l'objet que je lui passe pour avoir le type dynamique de l'objet avant d'appeler la fonction. (Lors de l'appel de la fonction setParams)
    Ceci me permet de simuler un système de fonctions templates virtuelles.

    Pour simplifier l'enregistrement des types et des fonctions, j'ai créer plusieurs macros, la 1ère ajoute juste une fonction non membre create dans le fichier.h d'une classe dérivée :

    Macro à appeler à la fin du fichier.h de chaque classe dérivées.
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    #define REGISTER_DERIVED(ID, BASE, TYPE) \
    BASE* create##ID() { \
        return new TYPE(); \
    }

    La seconde enregistre un type dérivé dans la factory :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    #define REGISTER_TYPE(ID, BASE, TYPE) \
    odfaeg::BaseFact<BASE>::register_type(typeid(TYPE).name(), &create##ID);

    Et la 3ème enregistre une fonction dans la factory, je suis obligé d'utiliser le suffixe vt (virtual template) devant le nom de la fonction car la macro ne peut pas concaténer le texte avec l'opérateur :: ce qui me donne ceci :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    #define REGISTER_FUNC(ID, funcName, BASE, TYPE, args...) \
    odfaeg::FastDelegate<void> delegate##ID (&TYPE::vt##funcName, args); \
    odfaeg::BaseFact<BASE>::register_function(typeid(TYPE).name(), delegate##ID);.

    Voilà et j'appelle ces 2 dernières macro au tout début du main pour enregistrer les fonctions et les types et pouvoir ainsi les appeler en fonction de leur type à l'exécution.

    Cependant il y a un soucis au linkage, le compilateur me ressors cette erreur :

    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
     
    ||=== Build: Debug in ODFAEG-DEMO (compiler: GNU GCC Compiler) ===|
    /usr/local/include/odfaeg/Physics/boundingBox.h|172|définitions multiples de « createBoundingBox() »|
    obj/Debug/caracter.o:/usr/local/include/odfaeg/Physics/boundingBox.h|172|défini pour la première fois ici|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Graphics/../../../include/odfaeg/Graphics/../Physics/boundingBox.h|172|définitions multiples de « createBoundingBox() »|
    obj/Debug/caracter.o:/usr/local/include/odfaeg/Physics/boundingBox.h|172|défini pour la première fois ici|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Graphics/../../../include/odfaeg/Graphics/../Physics/boundingBox.h|172|définitions multiples de « createBoundingBox() »|
    obj/Debug/caracter.o:/usr/local/include/odfaeg/Physics/boundingBox.h|172|défini pour la première fois ici|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Graphics/../../../include/odfaeg/Graphics/../Physics/boundingBox.h|172|définitions multiples de « createBoundingBox() »|
    obj/Debug/caracter.o:/usr/local/include/odfaeg/Physics/boundingBox.h|172|défini pour la première fois ici|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Graphics/2D/../../../../include/odfaeg/Graphics/2D/../../Physics/boundingBox.h|172|définitions multiples de « createBoundingBox() »|
    obj/Debug/caracter.o:/usr/local/include/odfaeg/Physics/boundingBox.h|172|défini pour la première fois ici|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Graphics/2D/../../../../include/odfaeg/Graphics/2D/../../Physics/boundingBox.h|172|définitions multiples de « createBoundingBox() »|
    obj/Debug/caracter.o:/usr/local/include/odfaeg/Physics/boundingBox.h|172|défini pour la première fois ici|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Graphics/2D/../../../../include/odfaeg/Graphics/2D/../../Physics/boundingBox.h|172|définitions multiples de « createBoundingBox() »|
    obj/Debug/caracter.o:/usr/local/include/odfaeg/Physics/boundingBox.h|172|défini pour la première fois ici|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Graphics/../../../include/odfaeg/Graphics/../Physics/boundingBox.h|172|définitions multiples de « createBoundingBox() »|
    obj/Debug/caracter.o:/usr/local/include/odfaeg/Physics/boundingBox.h|172|défini pour la première fois ici|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Graphics/../../../include/odfaeg/Graphics/../Physics/boundingBox.h|172|définitions multiples de « createBoundingBox() »|
    obj/Debug/caracter.o:/usr/local/include/odfaeg/Physics/boundingBox.h|172|défini pour la première fois ici|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Graphics/../../../include/odfaeg/Graphics/../Physics/boundingBox.h|172|définitions multiples de « createBoundingBox() »|
    obj/Debug/caracter.o:/usr/local/include/odfaeg/Physics/boundingBox.h|172|défini pour la première fois ici|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Physics/../../../include/odfaeg/Physics/boundingSphere.h|120|définitions multiples de « createBoundingSphere() »|
    obj/Debug/main.o:/usr/local/include/odfaeg/Physics/boundingSphere.h|120|défini pour la première fois ici|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Physics/../../../include/odfaeg/Physics/boundingBox.h|172|définitions multiples de « createBoundingBox() »|
    obj/Debug/caracter.o:/usr/local/include/odfaeg/Physics/boundingBox.h|172|défini pour la première fois ici|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Physics/../../../include/odfaeg/Physics/boundingSphere.h|120|définitions multiples de « createBoundingSphere() »|
    obj/Debug/main.o:/usr/local/include/odfaeg/Physics/boundingSphere.h|120|défini pour la première fois ici|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Physics/../../../include/odfaeg/Physics/boundingBox.h|172|définitions multiples de « createBoundingBox() »|
    obj/Debug/caracter.o:/usr/local/include/odfaeg/Physics/boundingBox.h|172|défini pour la première fois ici|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Physics/../../../include/odfaeg/Physics/boundingBox.h|172|définitions multiples de « createBoundingBox() »|
    obj/Debug/caracter.o:/usr/local/include/odfaeg/Physics/boundingBox.h|172|défini pour la première fois ici|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Physics/../../../include/odfaeg/Physics/boundingSphere.h|120|définitions multiples de « createBoundingSphere() »|
    obj/Debug/main.o:/usr/local/include/odfaeg/Physics/boundingSphere.h|120|défini pour la première fois ici|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Physics/../../../include/odfaeg/Physics/boundingSphere.h|123|définitions multiples de « createBoundingSphere() »|
    obj/Debug/main.o:/usr/local/include/odfaeg/Physics/boundingSphere.h|120|défini pour la première fois ici|
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Physics/../../../include/odfaeg/Physics/boundingBox.h|172|définitions multiples de « createBoundingBox() »|
    obj/Debug/caracter.o:/usr/local/include/odfaeg/Physics/boundingBox.h|172|défini pour la première fois ici|
    ||=== Build failed: 36 error(s), 0 warning(s) (0 minute(s), 5 second(s)) ===|
    Pourtant, je n'appelle qu'une seule fois la macro REGISTER_DERIVED dans les classe dérivée, je ne comprend pas pourquoi il me dit que la fonction est définie plusieurs fois.

    Voila merci d'avance pour votre aide. (Là j'ai le sentiment que je commence à avancer)

  7. #27
    Invité
    Invité(e)
    Par défaut
    Bon il suffisait de déclarer la fonction inline ...

    Et voilà ça fonctionne merci!!!

    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
     
    #ifndef ODFAEG_SERIALIZATION_HPP
    #define ODFAEG_SERIALIZATION_HPP
    #include <iostream>
    #include <typeinfo>
    #include "tuple.h"
    #include <tuple>
    #include <map>
    #include "fastDelegate.h"
    #define REGISTER_DERIVED(ID, BASE, TYPE) \
    inline BASE* create##ID() { \
        return new TYPE(); \
    }
    #define REGISTER_TYPE(ID, BASE, TYPE) \
    odfaeg::BaseFact<BASE>::register_type(typeid(TYPE).name(), &create##ID);
    #define REGISTER_FUNC(ID, FID, funcName, BASE, TYPE, args...) \
    odfaeg::FastDelegate<void> delegate##ID##FID (&TYPE::vt##funcName, args); \
    odfaeg::BaseFact<BASE>::register_function(typeid(TYPE).name(), #FID, delegate##ID##FID);
     
    namespace odfaeg {
    template <typename B>
    class BaseFact {
        public :
        static void register_type(std::string typeName, B*(*func)()) {
            typename std::map<std::string, B*(*)()>::iterator it = types.find(typeName);
            if (it == types.end()) {
                types[typeName] = func;
            }
        }
        static void register_function(std::string typeName, std::string funcName, FastDelegate<void> delegate) {
            typename std::map<std::string, FastDelegate<void>>::iterator it = functions.find(typeName + funcName);
            if (it == functions.end())
                functions[typeName+funcName] = delegate;
        }
        template <typename... A>
        static void callFunction(std::string typeName, std::string funcName, A... args) {
            typename std::map<std::string, FastDelegate<void>>::iterator it = functions.find(typeName+funcName);
                if (it != functions.end()) {
                    it->second.setParams(args...);
                    (it->second)();
                }
        }
        static B* create (std::string typeName) {
            typename std::map<std::string, B*(*)()>::iterator it = types.find(typeName);
            if (it != types.end()) {
                return (it->second)();
            }
            return nullptr;
        }
        static std::string getTypeName (B* type) {
            typename std::map<std::string, B*(*)()>::iterator it = types.find(typeid(*type).name());
            if (it != types.end())
                return it->first;
        }
        private :
        static std::map<std::string, B*(*)()> types;
        static std::map<std::string, FastDelegate<void>> functions;
    };
    template <typename B>
    std::map<std::string, B*(*)(void)> BaseFact<B>::types = std::map<std::string, B*(*)(void)>();
    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, Archive * ar) {
            BaseFact<B>::callFunction(typeid(*baseObject).name(), funcName, baseObject, ar);
        }
        B* sallocate(std::string typeName) {
            return BaseFact<B>::create(typeName);
        }
        std::string getTypeName() {
            return BaseFact<B>::getTypeName(baseObject);
        }
        private :
        B* baseObject;
    };
    }
    #endif // SERIALIZATION

    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
     
    #ifndef SERIALIZATION_IMPL
    #define SERIALIZATION_IMPL
    #include "serialization.h"
    #define REGISTER_BASE(KEY, TYPE) \
    struct KEY : public Serializer<TYPE> { \
        public : \
        KEY() : Serializer<TYPE>() {} \
        void register_object (TYPE* object) { \
            setObject(object); \
        } \
        TYPE* allocate_object(std::string typeName) { \
            return sallocate(typeName); \
        } \
        std::string getTypeName () { \
            return Serializer<TYPE>::getTypeName(); \
        } \
        template <typename Archive> \
        void serialize_object (std::string funcName, Archive * ar) { \
            serialize(funcName, ar); \
        } \
    }; \
    public : \
    KEY key; \
    typedef KEY KEYTYPE; \
    virtual void foo() {} \
    static TYPE* allocate (std::string typeName) { \
        static KEY aKey; \
        return aKey.allocate_object(typeName); \
    }
    #endif

    Dans la classe de base je met juste le type de base et l'id. (Et non plus la liste des types dérivés)

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    REGISTER_BASE(BOUNDINGVOLUMEKEY, odfaeg::BoundingVolume)

    Par contre je dois enregistrer les types dérivés à la fin des fichiers.h des classes dérivée :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    REGISTER_DERIVED(BoundingSphere, odfaeg::BoundingVolume, odfaeg::BoundingSphere)

    Dans l'archive je n'ai plus qu'à faire ceci lors de l'écriture :

    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
     
    //Dynamic objects.
        template <class O,
                  class... D,
                  class = typename std::enable_if<!std::is_fundamental<O>::value>::type,
                  class = typename std::enable_if<!std::is_same<O, std::string>::value>::type,
                  class = typename std::enable_if<has_typedef_key<O>::value>::type,
                  class = typename std::enable_if<!sizeof...(D)>::type>
        void operator() (O& object, D...) {
            if (typeid(decltype(object)) == typeid(object)) {
                object.vtserialize(this);
            } else {
                object.key.register_object(&object);
                object.key.serialize_object("OTextArchive", this);
            }
        }
        template <class O,
                  class... D,
                  class = typename std::enable_if<!std::is_fundamental<O>::value>::type,
                  class = typename std::enable_if<!std::is_same<O, std::string>::value>::type,
                  class = typename std::enable_if<has_typedef_key<O>::value>::type,
                  class = typename std::enable_if<!sizeof...(D)>::type>
        void operator() (O* object, D...) {
            std::map<unsigned long long int, unsigned long long int>::iterator it = adresses.find(reinterpret_cast<unsigned long long int>(object));
            if (it != adresses.end()) {
                buffer<<it->second<<" ";
            } else {
                std::string typeName = "BaseType";
                std::pair<unsigned long long int, unsigned long long int> newAddress (reinterpret_cast<unsigned long long int>(object), nbSerialized);
                adresses.insert(newAddress);
                if (typeid(decltype(*object)) == typeid(*object)) {
                    buffer<<newAddress.second<<" ";
                    buffer<<typeName<<std::endl;
                    object->vtserialize(this);
                } else {
                    object->key.register_object(object);
                    typeName = object->key.getTypeName();
                    buffer<<newAddress.second;
                    buffer<<typeName<<std::endl;
                    object->key.serialize_object("OTextArchive", this);
                }
                nbSerialized++;
            }
        }

    Et lors de la lecture :

    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
     
     //Dynamic objects.
        template <class O,
                  class... D,
                  class = typename std::enable_if<!std::is_fundamental<O>::value>::type,
                  class = typename std::enable_if<!std::is_same<O, std::string>::value>::type,
                  class = typename std::enable_if<has_typedef_key<O>::value>::type,
                  class = typename std::enable_if<!sizeof...(D)>::type>
        void operator() (O& object, D...) {
            if (typeid(decltype(object)) == typeid(object)) {
                object.vtserialize(this);
            } else {
                object.key.register_object(&object);
                object.key.serialize_object("ITextArchive", this);
            }
        }
        template <class O,
                  class... D,
                  class = typename std::enable_if<!std::is_fundamental<O>::value>::type,
                  class = typename std::enable_if<!std::is_same<O, std::string>::value>::type,
                  class = typename std::enable_if<has_typedef_key<O>::value && !std::is_abstract<O>::value>::type,
                  class = typename std::enable_if<!sizeof...(D)>::type>
        void operator() (O*& object, D...) {
     
            unsigned long long int id;
            std::string typeName;
            buffer>>id;
            getline(buffer, typeName);
            std::map<unsigned long long int, unsigned long long int>::iterator it = adresses.find(id);
            if (it != adresses.end()) {
                object = reinterpret_cast<O*>(it->second);
            } else {
                if (typeName == "BaseType") {
                     object = new O();
                     object->vtserialize(this);
                    std::pair<unsigned long long int, unsigned long long int> newAddress (id, reinterpret_cast<unsigned long long int>(object));
                    adresses.insert(newAddress);
                } else {
                    object = O::allocate(typeName);
                    object->key.register_object(object);
                    object->key.serialize_object("ITextArchive", this);
                    std::pair<unsigned long long int, unsigned long long int> newAddress (id, reinterpret_cast<unsigned long long int>(object));
                    adresses.insert(newAddress);
                }
                nbDeserialized++;
            }
        }
        template <class O,
                  class... D,
                  class = typename std::enable_if<!std::is_fundamental<O>::value>::type,
                  class = typename std::enable_if<!std::is_same<O, std::string>::value>::type,
                  class = typename std::enable_if<has_typedef_key<O>::value>::type,
                  class = typename std::enable_if<std::is_abstract<O>::value>::type,
                  class = typename std::enable_if<!sizeof...(D)>::type>
        void operator() (O*& object, D...) {
            std::string typeName;
            unsigned long long int id;
            buffer>>id;
            getline(buffer, typeName);
            std::map<unsigned long long int, unsigned long long int>::iterator it = adresses.find(id);
            if (it != adresses.end()) {
                object = reinterpret_cast<O*>(it->second);
            } else {
                object = O::allocate(typeName);
                object->key.register_object(object);
                object->key.serialize_object("ITextArchive", this);
                std::pair<unsigned long long int, unsigned long long int> newAddress (id, reinterpret_cast<unsigned long long int>(object));
                adresses.insert(newAddress);
                nbDeserialized++;
            }
        }

    Et enfin, dans le main, je n'ai plus qu'à enregistrer tout les types dérivés et toutes les fonctions que j'appelle pour sérialiser tout les types dérivés dans toutes les types d'archives :

    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
     
    REGISTER_TYPE(BoundingBox, odfaeg::BoundingVolume, odfaeg::BoundingBox)
        REGISTER_TYPE(BoundingSphere, odfaeg::BoundingVolume, odfaeg::BoundingSphere)
        sf::VideoMode mode(800, 600);
        sf::ContextSettings settings(0, 0, 4, 3, 0);
     
        odfaeg::RenderWindow window(mode, "test", sf::Style::Default, settings);
        odfaeg::Texture tex, tex2;
        tex.loadFromFile("tilesets/herbe.png");
        std::ostringstream oss;
        std::string text = "Ceci est un texte.";
        std::ofstream ofss("FichierDeSerialization.tex");
        {
            odfaeg::OTextArchive oa(ofss);
            oa(tex);
            //oa<<ofss;
        }
        ofss.close();
        std::istringstream iss;
        std::ifstream ifss("FichierDeSerialization.tex");
        {
            odfaeg::ITextArchive ia(ifss);
            ia(tex2);
            //ia>>ifss;
        }
        ifss.close();
        odfaeg::BoundingVolume* b1 = new odfaeg::BoundingSphere(odfaeg::Vec3f(0, 0, 0), 100);
        odfaeg::BoundingVolume* b2;
     
        std::ofstream ofs("FichierDeSerialisation");
        odfaeg::OTextArchive oa(ofs);
        REGISTER_FUNC(BoundingBox, OTextArchive, serialize, odfaeg::BoundingVolume, odfaeg::BoundingBox, new odfaeg::BoundingBox(), &oa);
        REGISTER_FUNC(BoundingSphere, OTextArchive, serialize, odfaeg::BoundingVolume, odfaeg::BoundingSphere, new odfaeg::BoundingSphere(), &oa);
        oa(b1);
        ofs.close();
     
        std::ifstream ifs("FichierDeSerialisation");
        odfaeg::ITextArchive ia(ifs);
        REGISTER_FUNC(BoundingBox, ITextArchive, serialize, odfaeg::BoundingVolume, odfaeg::BoundingBox, new odfaeg::BoundingBox(), &ia);
        REGISTER_FUNC(BoundingSphere, ITextArchive, serialize, odfaeg::BoundingVolume, odfaeg::BoundingSphere, new odfaeg::BoundingSphere(), &ia);
        ia(b2);
        std::cout<<static_cast<odfaeg::BoundingSphere*>(b2)->getCenter()<<" "<<static_cast<odfaeg::BoundingSphere*>(b2)->getRadius()<<std::endl;
        ifs.close();
    Et dans le fichier j'ai bien ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    0N6odfaeg14BoundingSphereE
    bounding volume
    0 0 0 1 100
    J'utilise un pointeur sur l'archive car ma classe FastDelegate ne fonctionne pas avec les références. :/

    Et voilà je n'ai plus qu'à lancer des exceptions si le développeur oublie d'enregistrer une fonction, ou bien un type dérivé.
    Dernière modification par Invité ; 30/08/2014 à 19h00. Motif: Fusion

  8. #28
    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
    Tant mieux!

    Content de voir que ca marche enfin.
    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

  9. #29
    Invité
    Invité(e)
    Par défaut
    Ouais moi aussi!

    Je me demande si il y aurait moyen d'enregistrer les types et les fonctions automatiquement, mais, je ne pense pas que ça soit possible, étant donné que je peux pas passer un pointeur sur la fonction courante comme le pointeurs this pour les objets. (Je ne pense pas que ça soit possible)

    Dommage que gcc n'aie pas un système pour enregistrer les fonctions templates pour les objets polymorphiques et permettre de pouvoir définir ainsi des fonctions template virtuelles.

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

Discussions similaires

  1. Obtenir un ensemble de solutions les plus différentes possibles
    Par karas.uchiwa dans le forum Algorithmes et structures de données
    Réponses: 2
    Dernier message: 30/03/2010, 12h28
  2. Réponses: 10
    Dernier message: 12/01/2006, 21h22
  3. [VBA]possible ou pas ? creer une image jpg a partir 7 jpg
    Par sakuraba dans le forum Général VBA
    Réponses: 5
    Dernier message: 03/01/2006, 10h45
  4. [Info]Solution CMS (Si possible JSP/Servlets)
    Par lolo le belge dans le forum Servlets/JSP
    Réponses: 6
    Dernier message: 16/12/2005, 22h55
  5. Permuter des valeurs, le plus rapidement possible?
    Par danje dans le forum Algorithmes et structures de données
    Réponses: 4
    Dernier message: 27/09/2005, 21h51

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