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 :

Sérialisation classe template


Sujet :

Boost C++

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2018
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Service public

    Informations forums :
    Inscription : Décembre 2018
    Messages : 2
    Points : 1
    Points
    1
    Par défaut Sérialisation classe template
    bonjour,
    j'aimerai sérialiser un objet d'une classe template qui dérive d'une classe mère template.
    J'ai essayé depuis 5 jours en suivant les instructions dans les différents forums et tutos boost sans succès.
    Voici, comment je procède pour la sérialisation (qui ne marche 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
    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
    template<class T>
    class a
    {
    public:
     a::a() {}
     virtual double f(T& x, T& y);
    private:
        friend class boost::serialization::access;
        template<class Archive>
        void serialize(Archive & ar, const unsigned int version);
    }
    template<class T>
    template<class Archive>
    void a<T>::serialize(Archive & ar, const unsigned int version)
    {
        BOOST_SERIALIZATION_ASSUME_ABSTRACT(a);
    }
     
    /// classe derivée
     
    template<class T>
    class b : public a
    {
    public:
    b::b() {}
     virtual double f(T& x, T& y);
    private:
        friend class boost::serialization::access;
        template<class Archive>
        void serialize(Archive & ar, const unsigned int version);
    }
     
    template<class T>
    template<class Archive>
    void b<T>::serialize(Archive & ar, const unsigned int version)
    {
        typedef a<T> baseClass;
        ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(baseClass);
        ar & BOOST_SERIALIZATION_NVP(*this);
     
        //ar & boost::serialization::make_nvp("Base", boost::serialization::base_object< a<T> >(*this) ); //ne marche pas    
        //ar & boost::serialization::base_object< a<T> >(*this);
     
    }
    BOOST_CLASS_EXPORT_KEY(b<double>); // ne marche pas 
    //BOOST_CLASS_EXPORT(b<double>); // ne marche pas
    //BOOST_CLASS_EXPORT_GUID(b<double>, "idClasseB"); //ne marche pas
    J'ai une erreur "multiple definition" de classe b. J'ai fait des modifications à plusieurs endroits et testé plusieurs variantes mais ça ne marche pas. Au bout de plusieurs jours, je n'arrive toujours pas à trouver mon erreur.

    Merci par avance pour votre aide.

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 611
    Points
    30 611
    Par défaut
    Salut,

    Il faut faire très attention avec les template, parce que cela dresse un maximum d'embûches sur ton chemin

    La première, dans laquelle tu ne semble pas être tombé, c'est que, pour que le compilateur soit en mesure de fournir le code binaire qui correspond à une fonction (membre de classe) template, l'implémentation de la fonction doit se trouver dans le fichier d'en-tête (ou, à tout le moins, dans un fichier qui pourra être inclus n'importe où)

    La deuxième, c'est que, comme l'implémentation de la fonction se fait dans le fichier d'en-tête, le compilateur va produire le code binaire exécutable d'une fonction (membre de classe) template dans ... toutes les unités de compilations qui font appel à cette fonction.

    Du coup, si aucune mesure n'est prise pour se prémunir du problème, lorsque l'éditeur de liens voudra regrouper les différents fichiers objet, correspondant aux différentes unités de compilation, il va se retrouver avec autant de fonction portant le même nom (à la spécialisation template près) que d'unités de compilations dans lesquelles la fonction (membre de classe) template occasionné la création du code binaire, et il ne sera pas en mesure de déterminer "quelle version" du code binaire de la fonction il doit lier à "quel appel" de la fonction.

    Pour utiliser le terme technique : ton problème vient du fait que le code ne respecte pas une règle appelée ODR (One Definition Rule en anglais, ou Règle de la définition unique, si tu préfères en français )

    Pour éviter ce problème, il faut faire en sorte que le compilateur considère la fonction en question comme étant inline. Cela lui permettra de laisser des instructions à l'éditeur de lien afin de lui permettre de prendre "toutes les mesures nécessaires" (il a plusieurs solutions possibles ) pour éviter les conflits.

    Quand il s'agit d'une fonction membre de classe, une des solutions consiste implémenter la fonction directement de la classe. une autre consistant simplement à déclarer explicitement la fonction comme étant inline

    Ceci étant dit, j'aurais quand même quelques remarques à faire sur le code que tu nous montre :

    D'abord, il faut savoir que la virtualité ne se marie vraiment pas bien avec les classes template, surtout quand il s'agit de classe de base.

    Si tu dois changer le comportement d'une fonction membre d'une classe de base template, tu as sans doute intérêt à, tout simplement, envisager la spécialisation (partielle ou totale) de la fonction pour l'adapter au type des paramètres que tu lui transmettra.

    En outre, la sérialisation n'a réellement de l'intérêt que ... s'il y a des données à sauvegarder, dans le but de pouvoir les récupérer par la suite.

    Je me doute plus ou moins que tu as "simplement" pris la peine de nettoyer ton code pour nous fournir un exemple minimal (non) compilable qui reproduise le problème, mais, comme ni ta classe de base ni ta classe dérivée ne dispose de données membres, il me semble opportun d'effectuer ce rappel

    Enfin, ce n'est encore une fois sans doute qu'une erreur de copie, mais... n'aurais tu pas oublié le point-virgule ";" après l'accolade fermante qui met fin à la définition de tes classes
    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

  3. #3
    Nouveau Candidat au Club
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2018
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Service public

    Informations forums :
    Inscription : Décembre 2018
    Messages : 2
    Points : 1
    Points
    1
    Par défaut
    Bonjour koala01,

    merci pour ta réponses et les rappels. Le point-virgule je l'ai oublié juste ici mais dans le code il y est bien.
    Le problème que j'ai cité est lié à la librairie de sérialisation Boost et j'ai déjà cherché sur d'autres forums (anglophones) concernant le cas particulier des templates.

    Le truc est que ce code est fourni dans une librairie que j'utilise dans mon travail et que les gens qui ont fait ça ont prévu la sérialisation d'objets pour tous les membres de la classe A à laquelle ils appartiennent sauf un membre : celui qui est lui même un objet de la classe template (dérivant d'une autre classe template). Cette classe n'a pas de membres (données) mais elle a des fonctions membres (qui font des plusieurs calculs de distances en fonction du type de données en entrée). Il faut donc sérialiser, non seulement les données (ceci concerne les autres membres de A mais aussi le type d'algorithme de distance utilisé (qui est un objet de la classe template fille dérivant d'une autre classe templatée). J'étais donc surpris de voir que les développeurs de cette librairie n'ont pas pris en charge la sérialisation de ce membre, alors j'avais entrepris de le faire. Maintenant, avec toutes les difficultés que je trouve à le faire, je comprends mieux pourquoi ils ne l'ont pas fait .

    Merci par avance.

Discussions similaires

  1. Boost, serialisation et classe virtuelle pure.
    Par AF_2.8 dans le forum Boost
    Réponses: 3
    Dernier message: 06/12/2010, 11h14
  2. Boost serialize xml et class template
    Par EmlTakeo dans le forum Boost
    Réponses: 1
    Dernier message: 22/08/2008, 10h27
  3. [DLL/classe template] problème de link
    Par Bob.Killer dans le forum C++
    Réponses: 7
    Dernier message: 31/08/2005, 19h56
  4. Class template hérité
    Par Azharis dans le forum Langage
    Réponses: 4
    Dernier message: 24/06/2005, 23h03
  5. Réponses: 6
    Dernier message: 06/10/2004, 13h59

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