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

Boost C++ Discussion :

boost::serialization et std::unique_ptr


Sujet :

Boost C++

  1. #1
    Membre éclairé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2008
    Messages
    836
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2008
    Messages : 836
    Par défaut boost::serialization et std::unique_ptr
    Je cherchais un moyen de sauvegarder/charger des données de mon projet, et je suis tombé sur boost::serialization qui avait l'air pas mal sur le papier.
    Sur le papier, parce qu'il semble qu'il ne supporte pas les std::unique_ptr, et j'ai moyennement envie de faire passer tout mon projet aux pointeurs nus (quoique parfois j'hésite, vues les galères que les unique_ptr m'infligent...le souci c'est que je préfère diminuer le risque de fuites mémoires, surtout si quelqu'un décide de contribuer...)...

    Vu que je n'ai jamais utilisé boost::serialization avant et que je doute franchement d'avoir tout compris par rapport à son usage, je me demande si ce n'est pas plutôt moi qui ai merdé quelque part. (A moins que le problème ne vienne d'une mauvaise utilisation de std::unique_ptr... ça ne m'étonnerait pas outre mesure non plus.)

    Le problème viens du fait que le constructeur par copie est appelé par boost::interface_iarchive::operator>>(...) . J'aurai pu simplement lui passer un pointeur brut issu de mon unique_ptr, sauf que celui-ci est en fait possédé par un vector et qu'une telle opération impliquerais d'itérer sur le vecteur, hors, j'ai cru comprendre que boost était capable de le faire lui-même.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    void LoadTextFile::installEventManager(RenderWindow & target) throw()
    {
    	...
    	...
    	...
    	std::string filename(openFile.GetPath());
    	std::ifstream ifs(filename);
    	boost::archive::text_iarchive ia(ifs);
    	ia >> static_cast<Group&>(target);// génère l'erreur, bien qu'elle ne soit pas vraiment causée par cette ligne
    	//target  contiens un std::vector<std::unique_ptr<Object>> qui doit être sérializé et qui cause le problème
    }
    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
     
    ...
    #include <boost/serialization/vector.hpp>
    ...
     
    class Group : public Object
    {
    	...
    	...
    	...
    	private:
    		template<class Archive>
    		void serialize(Archive & ar, const unsigned int version)
    		{
    			ar & m_children;
    		}
     
    	public:
    	protected:
    		std::vector<std::unique_ptr<Object>> m_children;
    }
    Si quelqu'un à une idée de comment résoudre ce problème, je suis preneur... Ou même si quelqu'un me dis que boost en est incapable. Si c'est le cas, je ferais une solution "maison" même si je préfère éviter de réinventer la roue :/

  2. #2
    Membre éclairé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2008
    Messages
    836
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2008
    Messages : 836
    Par défaut
    Hum, après avoir fouillé un peu, il semble qu'il faille enregistrer les pointeurs (je l'avais lu, mais sans y faire attention... pourtant, c'est logique ).

    Du coup, j'ai ajouté le code que je suppose nécessaire, ce qui donne donc:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    	boost::archive::text_iarchive ia(ifs);
    	ia.register_type(static_cast<std::unique_ptr<Group>>(nullptr));
    	ia.register_type(static_cast<std::unique_ptr<RenderWindow>>(nullptr));
    	ia.register_type(static_cast<std::unique_ptr<Shape>>(nullptr));
    	boost::serialization::void_cast_register(static_cast<std::unique_ptr<Group>>(nullptr),static_cast<std::unique_ptr<Object>>(nullptr));
    	boost::serialization::void_cast_register(static_cast<std::unique_ptr<RenderWindow>>(nullptr),static_cast<std::unique_ptr<Object>>(nullptr));
    	boost::serialization::void_cast_register(static_cast<std::unique_ptr<Shape>>(nullptr),static_cast<std::unique_ptr<Object>>(nullptr));
    	ia >> static_cast<Group&>(target);
    Sauf que du coup, j'ai des erreurs complètement différentes et pas spécialement très claires (ah, les templates...)
    In member function 'virtual void LoadTextFile::installEventManager(RenderWindow&)':
    error: no matching function for call to ‘boost::archive::text_iarchive::register_type(std::unique_ptr<Group>)’
    note: candidate is:
    note: template<class T> const boost::archive::detail::basic_pointer_iserializer* boost::archive::detail::interface_iarchive::register_type(T*) [with T = T; Archive = boost::archive::text_iarchive]
    note: template argument deduction/substitution failed:
    note: mismatched types ‘T*’ and ‘std::unique_ptr<Group>’|
    Conclusion, j'ai toujours l'impression que je vais en ch*** pour utiliser std::unique_ptr

  3. #3
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Je ne connais pas boost::serialization, mais dans la doc je vois ca :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    sa.register_type<T>() 
    sa.register_type(u)
    T is an Serializable Type
    u is a pointer to a an instance of type T
    A type T is Serializable if and only if one of the following is true:
    [...]
    It is a class type and one of the following has been declared according to the prototypes detailed below:
    a class member function serialize
    a global function serialize
    As-tu bien vérifier l'ensemble de ces conditions ?

  4. #4
    Membre éclairé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2008
    Messages
    836
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2008
    Messages : 836
    Par défaut
    Merci de ta réponse.
    J'ai bien ajouté les méthodes "template<class Archive> void serialize(Archive & ar, const unsigned int version)" dans chaque classe qui nécessite d'être sérialisée.

    Je pense que mon souci viens plus du souci indiqué par cette ligne d'erreur : "mismatched types 'T*' and 'std::unique_ptr<Group>' ". Il est évident qu'il ne s'agit pas des même types, puisque std::unique_ptr est une classe. Ok, elle agit (presque) comme un pointeur mais pas tout à fait, et de toute façon le compilo ne regarde mais ce que ça fait, mais ce que c'est.

    Pour tout ce qui concerne les collections, ils ont ajouté des headers correspondants. Par exemple pour les vector: "#include <boost/serialization/vector.hpp>". Il aurait fallu un équivalent pour "#include <memory>" mais je n'en ai pas trouvé :S

    EDIT:
    A noter qu'il semble qu'il y ait ces headers pour shared_ptr, weak_ptr et scoped_ptr, sauf que bon, ce n'est pas ces pointeurs que j'ai utilisé (et pour cause, je n'utilise pas de pointeurs possédé par plusieurs personnes, et je ne sais même pas à quoi correspond scoped_ptr)

  5. #5
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Je vais essayer d'expliciter un peu plus :

    1/ As-tu vérifier que std::unique_ptr<T> est serializable si T l'est ? Si ce n'est pas le cas (et je pense que ca ne l'est pas, mais à vérifier tout de même, je ne connais pas boost::serializable), as-tu fais quelque chose pour rendre std::unique_ptr<T> serializable si T l'est ?

    2/ Dit autrement, as-tu écris une fonction serialize propre à un/des std::unique_ptr (de manière générique peut-être ?) ? Si ce n'est pas le cas, alors à moins que boost le fasse par défaut, std::unique_ptr n'a aucune raison d'être serializable.

    Suite à ton edit: Regardes la doc de boost::scoped_ptr, c'est comme std::unique_ptr la move semantic en moins.

  6. #6
    Membre éclairé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2008
    Messages
    836
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2008
    Messages : 836
    Par défaut
    Hum, bien vu. Logiquement, unique_ptr<T> ne devrais pas être sérialisable de la même façon qu'un objet classique. Et je doute qu'il soit possible qu'il expose une interface qui le rende sérialisable, puisque le but n'est que d'imiter un pointeur.

    Donc, on dirait qu'il va falloir que je fouille le source de boost pour appliquer ce qu'ils ont fait aux pointeurs bruts sur un std::unique_ptr.

    Ca risque d'être pénible, mais c'est une piste.

    Au cas où, vu que je n'ai rien trouvé sur ce sujet sur le net, j'ai également envoyé un mail sur la ML utilisateurs. J'attends qu'il y ait une réponse avant de commencer à perdre du temps a tenter d'implémenter quelque chose qui existe peut-être déjà.

  7. #7
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Regardes le code de serialize pour boost::scoped_ptr. Tu dois faire la même chose pour std::unique_ptr :
    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
     
    template<class Archive, class T>
        void serialize(
            Archive& ar, 
            boost::scoped_ptr< T >& t, 
            const unsigned int version
        ){
            boost::serialization::split_free(ar, t, version);
        }
     
    //Surment en
     
    template<class Archive, class T>
        void serialize(
            Archive& ar, 
            std::unique_ptr< T >& t, 
            const unsigned int version
        ){
            boost::serialization::split_free(ar, t, version);
        }
     
    //A vérifier quand même dans la doc à quoi sert split_free
    //j'ai écris ça sans regarder
    //mais il vaut mieux comprendre que de faire un simple remplacement
    //si après ça marche pas à cause d'une subtilité
    //ca sera introuvable.
    Par contre ça ne marche pas pour les std::unique_ptr sur des types primitif. Et il y a peut-être d'autre fonctions à adapter, regardes l'ensemble des fonctions qui peuvent exister pour boost::scoped_ptr (en comprenant ce qu'elles font bien entendu).

  8. #8
    Membre éclairé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2008
    Messages
    836
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2008
    Messages : 836
    Par défaut
    J'ai eu une réponse intéressante, bien que je n'aie pas testé le code.
    Voici le lien qui m'a été donné: http://www.savarese.com/software/wis...29_source.html

    [Reste de la discussion concernant l'intérêt de unique_ptr déplacé dans http://www.developpez.net/forums/d12...r/#post6845588 ]

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

Discussions similaires

  1. Réponses: 6
    Dernier message: 31/08/2007, 21h05
  2. Boost::Serialize
    Par Rodrigue dans le forum Bibliothèques
    Réponses: 19
    Dernier message: 26/07/2007, 16h09
  3. Librairie boost::serialization + vector : possible ?
    Par zax-tfh dans le forum Bibliothèques
    Réponses: 6
    Dernier message: 07/01/2006, 14h15
  4. boost::serialize
    Par Fry dans le forum Bibliothèques
    Réponses: 6
    Dernier message: 05/11/2004, 18h03

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