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

C++ Discussion :

shared_ptr et composite


Sujet :

C++

  1. #1
    Membre confirm�
    Profil pro
    Inscrit en
    F�vrier 2007
    Messages
    142
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2007
    Messages : 142
    Par d�faut shared_ptr et composite
    Bonjour � tous,

    J'ai une classe conteneur directory et une classe directory_item (dont va d�river la classe directory et une classe file). Un objet directory contient une liste de directory_item (via des shared_ptr), et directory_item conna�t son r�pertoire parent (via un weak_ptr).
    La classe directory comporte une fonction membre add(directory_item) qui, en plus d'alimenter la liste de directory_item, a la responsabilit� d'informer l'objet directory_item en question qui est son r�pertoire parent (via directory_item::parent()). Cela donne une double responsabilit�, c'est peut-�tre l� que �a p�che ?
    Attention c'est (un peu) C++0x :
    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
     
    class directory_item;
     
    class directory: public directory_item
    {
        public:
            void
            add(std::shared_ptr<directory_item> an_item);
     
        private:
            std::list<std::shared_ptr<directory_item>> m_items;
    };
     
    class directory_item
    {
        public:
            void
            parent(std::weak_ptr<directory> parent_directory);
     
        private:
            std::weak_ptr<directory> m_parent_directory;
    };
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    void
    directory::add(std::shared_ptr<directory_item> an_item)
    {
        m_items.push_back(an_item);
        an_item->parent(???); //que mettre ici ?
    }
    
    void
    directory_item::parent(std::weak_ptr<directory> parent_directory)
    {
        m_parent_directory = parent_directory;
    }
    La ligne qui me pose probl�me est en rouge.
    En premier, j'ai essay� this qui �videmment ne compile pas.
    Ensuite, j'ai utilis� std::shared_from_this(), mais il semblerait que le weak_ptr directory_item::m_parent_directory devienne imm�diatement invalide juste apr�s son affectation. Le compteur de r�f�rence du shared_ptr r�sultant de std::shared_from_this() doit tomber � z�ro� pourtant le directory n'est pas d�truit (peut-�tre que le deleter du shared_ptr est sans effet ? http://www.boost.org/doc/libs/1_36_0...es.html#static).

    Quoi qu'il en soit, il semblerait que le weak_ptr � passer en param�tre � directory_item::parent(directory) doive �tre cr�� � partir d'un shared_ptr persistant.
    Dans ce cas, la seule solution qui me reste serait de cr�er une fonction libre ayant la signature ci-dessus, que l'objet directory pourra appeler pour obtenir un shared_ptr persistant sur lui-m�me � partir de *this :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
     
    std::shared_ptr<directory> find_directory(filesystem&, const directory&);
    Est-ce que ma fa�on de penser est correcte ?
    Si oui, est-ce que la solution que je donne est la bonne ?

  2. #2
    R�dacteur/Mod�rateur
    Avatar de JolyLoic
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Ao�t 2004
    Messages
    5 463
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 51
    Localisation : France, Yvelines (�le de France)

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

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 5 463
    Par d�faut
    Je ne vois pas a priori de probl�me � passer shared_from_this() � la fonction parent. Peux-tu montrer ton code dans ce cas ?

    Un cas qui pourrait poser probl�me, c'est si add est appel� depuis le constructeur de directory. En effet, � ce moment, l'objet n'a pas encore fini d'�tre cr��, et donc il n'a pas encore �t� affect� au pointeur intelligent qui va le g�rer, et donc shared_from_this ne fonctionne pas bien. Dans ce cas, la solution passe souvent par une factory qui dans ton cas ressemblerait � :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    shared_ptr<Directory> createDirectory(/*args*/)
    {
        shared_ptr<Directory> result(new Directory(/*args*/); // Pas de lecture du contenu ici
        result->readContent(); // Ici, add marchera
        return result;
    }
    J'en parle un peu dans mon article sur le sujet : http://loic-joly.developpez.com/tuto...mart-pointers/
    Ma session aux Microsoft TechDays 2013 : D�velopper en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage � la d�couverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'h�sitez pas � me contacter.

  3. #3
    Membre confirm�
    Profil pro
    Inscrit en
    F�vrier 2007
    Messages
    142
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2007
    Messages : 142
    Par d�faut
    Un cas qui pourrait poser probl�me, c'est si add est appel� depuis le constructeur de directory.
    Pas de probl�me de ce c�t�, ce n'est pas le cas.

    J'en parle un peu dans mon article sur le sujet : http://loic-joly.developpez.com/tuto...mart-pointers/
    Oui, c'est en lisant ton tr�s chouette article que j'ai �t� convaincu de l'utilit� des smart pointers

    Peux-tu montrer ton code dans ce cas ?
    En r�alit�, il s'agit d'une classe namespace_ (comme un namespace C++) et non d'une classe directory dans mon code. Mais le principe est le m�me :
    Code namespace_.h : 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
     
    #ifndef CPPPARSER_PROGRAM_MODEL_NAMESPACE_H
    #define CPPPARSER_PROGRAM_MODEL_NAMESPACE_H
     
    #include <string>
    #include <vector>
    #include <memory>
    #include "namespace_item.h"
     
    namespace cppparser { namespace program_model
    {
     
    class class_;
    class enum_;
    class typedef_;
     
    /**
    Represents a C++ namespace.
    */
    class namespace_: public namespace_item, public std::enable_shared_from_this<namespace_>
    {
        public:
            /**
            Creates an anonymous namespace. Equivalent to namespace_("").
            */
            namespace_();
     
            /**
            Creates a named namespace.
            @param name the namespace's name.
            */
            explicit namespace_(const std::string& name);
     
            /**
            Destructor.
            */
            ~namespace_();
     
            /**
            @return the name of the namespace.
            Anonymous namespaces return an empty string.
            */
            const std::string&
            name() const;
     
            /**
            @return the full name of the namespace, including all parents (e.g. ::foo::bar).
            */
            std::string
            full_name() const;
     
            /**
            @return true if the namespace is the global one, false otherwise.
            */
            bool
            is_global() const;
     
            /**
            Check whether an already declared symbol has the given name.
            @param name the name of the namespace to search.
            @return true if an already existing namespace has the same name, false otherwise.
            */
            std::shared_ptr<namespace_>
            find_namespace(const std::string& name) const;
     
            /**
            @return the item list of the namespace, i.e. the list of classes, function, etc.
            */
            const std::vector<std::shared_ptr<namespace_item>>&
            items() const;
     
            /*void
            add(std::shared_ptr<namespace_item> a_namespace_item);*/
     
            void
            add(std::shared_ptr<namespace_> a_namespace);
     
            ///@todo find better than that dirty trick
            void
            shared_this(std::shared_ptr<namespace_> ptr);
     
        private:
            std::string m_name;
            std::shared_ptr<namespace_> m_shared_this;
            std::vector<std::shared_ptr<namespace_item>> m_items;
            std::vector<std::shared_ptr<namespace_>> m_namespaces;
    };
     
    }} //namespace cppparser::program_model
    #endif
    Code namespace_.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
     
    #include <iostream>
    #include <algorithm>
    #include <stdexcept>
    #include "class_.h"
    #include "enum_.h"
    #include "typedef_.h"
     
    #include "namespace_.h"
     
    namespace cppparser { namespace program_model
    {
     
    namespace_::namespace_()
    {
    }
     
    namespace_::namespace_(const std::string& name):
        m_name(name)
    {
    }
     
    namespace_::~namespace_()
    {
    }
     
    const std::string&
    namespace_::name() const
    {
        return m_name;
    }
     
    std::string
    namespace_::full_name() const
    {
        std::string full_name;
     
        if(!is_global())
        {
            full_name = parent().lock()->full_name() + "::";
        }
        full_name += m_name;
     
        return full_name;
    }
     
    bool
    namespace_::is_global() const
    {
        return !has_parent();
    }
     
    std::shared_ptr<namespace_>
    namespace_::find_namespace(const std::string& name) const
    {
        ///@todo use STL algo. instead
        for
        (
            std::vector<std::shared_ptr<namespace_>>::const_iterator i = m_namespaces.begin();
            i != m_namespaces.end();
            ++i
        )
        {
            std::shared_ptr<namespace_> n = *i;
            if(n->name() == name)
            {
                return n;
            }
        }
     
        return std::shared_ptr<namespace_>(); //return a null pointer if no namespace found
    }
     
     
     
    const std::vector<std::shared_ptr<namespace_item>>&
    namespace_::items() const
    {
        return m_items;
    }
     
    void
    namespace_::add(std::shared_ptr<namespace_> a_namespace)
    {
        //check whether no already existing namespace has the same name
        if(find_namespace(a_namespace->name()))
        {
            throw std::runtime_error(full_name() + " already contains a namespace named \"" + a_namespace->name() + "\".");
        }
     
        //tell namespace that we (i.e. this) are its parent
        a_namespace->parent(shared_from_this()); //si on laisse cette ligne, on a le droit à un std::bad_weak_ptr à l'exécution
        //a_namespace->parent(shared_this); //par contre, si on met ceci à la place, tout se passe correctement… mais c'est un peu sale, comme code
        a_namespace->shared_this(a_namespace); ///< @todo find better than that dirty trick
     
        //add namespace to private containers
        m_namespaces.push_back(a_namespace);
        m_items.push_back(a_namespace);
    }
     
    void
    namespace_::shared_this(std::shared_ptr<namespace_> ptr)
    {
        m_shared_this = ptr;
    }
     
    }} //namespace cppparser::program_model
    Code namespace_item.h : 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
     
    #ifndef CPPPARSER_PROGRAM_MODEL_NAMESPACE_ITEM_H
    #define CPPPARSER_PROGRAM_MODEL_NAMESPACE_ITEM_H
     
    #include <memory>
     
    namespace cppparser { namespace program_model
    {
     
    class namespace_;
     
    class namespace_item
    {
        public:
            virtual ~namespace_item();
     
            bool
            has_parent() const;
     
            std::weak_ptr<namespace_>
            parent();
     
            const std::weak_ptr<namespace_>
            parent() const;
     
            void
            parent(std::weak_ptr<namespace_> parent);
     
        private:
            std::weak_ptr<namespace_> m_parent;
    };
     
    }} //namespace cppparser::program_model
     
    #endif
    Code namespace_item.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
     
    #include <iostream>
    #include "program.h"
     
    #include "namespace_item.h"
     
    namespace cppparser { namespace program_model
    {
     
    namespace_item::~namespace_item()
    {
    }
     
    bool
    namespace_item::has_parent() const
    {
        return !m_parent.expired();
    }
     
    std::weak_ptr<namespace_>
    namespace_item::parent()
    {
        return m_parent;
    }
     
    const std::weak_ptr<namespace_>
    namespace_item::parent() const
    {
        return m_parent;
    }
     
    void
    namespace_item::parent(std::weak_ptr<namespace_> parent)
    {
        m_parent = parent;
    }
     
    }} //namespace cppparser::program_model

    EDIT : J'ajoute aussi la classe program, contenant le namespace global.
    Le namespace global �tant cr�� statiquement, j'utilise un shared_ptr avec un deleter sans effet :
    Code program.h : 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 CPPPARSER_PROGRAM_MODEL_PROGRAM_H
    #define CPPPARSER_PROGRAM_MODEL_PROGRAM_H
     
    #include <memory>
    #include "namespace_.h"
     
    namespace cppparser { namespace program_model
    {
     
    /**
    Represents a C++ program.
    A program can be either an executable or a library.
    */
    class program
    {
        public:
            program();
     
            /**
            @return the global namespace of the program.
            */
            std::shared_ptr<namespace_>
            global_namespace();
     
        private:
            namespace_ m_global_namespace;
            std::shared_ptr<namespace_> m_global_namespace_ptr;
    };
     
    }} //namespace cppparser::program_model
     
    #endif
    Code program.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
     
    #include "program.h"
     
    namespace cppparser { namespace program_model
    {
     
    namespace
    {
    struct null_deleter
    {
        void operator()(void const *) const
        {
        }
    };
    }
     
    program::program():
        m_global_namespace_ptr(&m_global_namespace, null_deleter())
    {
        m_global_namespace.shared_this(m_global_namespace_ptr);
    }
     
    std::shared_ptr<namespace_>
    program::global_namespace()
    {
        return m_global_namespace_ptr;
    }
     
    }} //namespace cppparser::program_model

  4. #4
    R�dacteur/Mod�rateur
    Avatar de JolyLoic
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Ao�t 2004
    Messages
    5 463
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 51
    Localisation : France, Yvelines (�le de France)

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

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 5 463
    Par d�faut
    Citation Envoy� par three minute hero Voir le message
    EDIT : J'ajoute aussi la classe program, contenant le namespace global.
    Le namespace global �tant cr�� statiquement, j'utilise un shared_ptr avec un deleter sans effet :
    Ah, enfin un truc un peu louche dans ton code

    Je ne suis pas certain que ce soit li�, mais pourquoi ne pas avoir simplement un namespace global cr�� dynamiquement comme les autres, et dans ta classe program, une seul variable membre, de type std::shared_ptr<namespace_> ?

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    program::program():
        m_global_namespace_ptr(new(namespace_))
    {
    }

    Autre point, sans rapport avec ton probl�me, pourquoi ne pas faire retourner � namespace_item::parent() un shared_ptr, tout en gardant un weak_ptr comme donn�e membre ? Ca simplifierait probablement l'utilisation de cette fonction.
    Ma session aux Microsoft TechDays 2013 : D�velopper en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage � la d�couverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'h�sitez pas � me contacter.

  5. #5
    Membre confirm�
    Profil pro
    Inscrit en
    F�vrier 2007
    Messages
    142
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2007
    Messages : 142
    Par d�faut
    Citation Envoy� par JolyLoic Voir le message
    Ah, enfin un truc un peu louche dans ton code

    Je ne suis pas certain que ce soit li�, mais pourquoi ne pas avoir simplement un namespace global cr�� dynamiquement comme les autres, et dans ta classe program, une seul variable membre, de type std::shared_ptr<namespace_> ?
    Parc'queeeee ! C'est pas optimis� comme �a ! Et �a n'a rien d'une optimisation pr�matur�e. On est pas en java .
    Bien, plus s�rieusement, je teste �a imm�diatement.
    (�)
    H�las cela ne change rien. De plus, que le namespace global soit cr�� dynamiquement ou statiquement, si j'utilise le syst�me que j'ai mis en place le temps de r�gler ce probl�me, tout fonctionne bien :
    Le propri�taire de chaque namespace passe au namespace une copie d'un shared_ptr vers lui-m�me (le namespace), voir namespace_::shared_this() et m_shared_this.
    Ainsi, lors de l'ex�cution de namespace_::add(), o� le namespace doit passer un pointeur vers lui-m�me � son enfant (le namespace_item, ou dans mon code le namespace_ tout court, car je vais surcharger add() pour chaque type d'item), le namespace n'a plus qu'� passer m_shared_this � son enfant (le fameux shared_ptr persistant dont j'ai parl� dans mon premier post) en lieu et place o� j'aimerais plut�t �crire shared_from_this().
    �a renforce l'hypoth�se que le probl�me vient de shared_from_this(). Si je laisse shared_from_this(), j'ai immanquablement droit � une exception de type bad_weak_ptr.

    Citation Envoy� par JolyLoic Voir le message
    Autre point, sans rapport avec ton probl�me, pourquoi ne pas faire retourner � namespace_item::parent() un shared_ptr, tout en gardant un weak_ptr comme donn�e membre ? Ca simplifierait probablement l'utilisation de cette fonction.
    Il me semblait qu'un shared_ptr g�n�r� � partir d'un weak_ptr devait rester le plus temporaire possible. D'autant plus que la fonction pour obtenir ce shared_ptr s'appelle weak_ptr::lock(). �a sonne un peu mutex, �a me donne pas envie de cr�er un shared_ptr persistant � partir de �a !

  6. #6
    R�dacteur/Mod�rateur
    Avatar de JolyLoic
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Ao�t 2004
    Messages
    5 463
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 51
    Localisation : France, Yvelines (�le de France)

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

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 5 463
    Par d�faut
    Pour ton probl�me, j'essayerais de regarder �a ce soir...

    Pour le retour de fonction, il est justement temporaire. Est-ce que tu vois un cas d'utilisation o� tu peux vouloir appeler la fonction parent sans regarder ce que vaut justement ce parent ?
    Ma session aux Microsoft TechDays 2013 : D�velopper en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage � la d�couverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'h�sitez pas � me contacter.

  7. #7
    Membre confirm�
    Profil pro
    Inscrit en
    F�vrier 2007
    Messages
    142
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2007
    Messages : 142
    Par d�faut
    Bien bien bien.
    J'ai repris le probl�me ce matin.

    D�j�, j'ai fait en sorte que namespace_ store un weak_ptr vers lui-m�me, et non un shared_ptr. Les objets namespace_ n'�taient jamais d�truits, forc�ment, vu que le compteur �tait au minimum � 1.
    �a, c'est d�j� une bonne chose de faite, et en plus �a nous rapproche de ce que fait enable_shared_from_this en interne (voir ici).

    Maintenant que le probl�me est encore plus cibl�, j'ai pu un peu mieux relire la page de la doc de boost concernant enable_shared_from_this, o� il est �crit tr�s clairement que :
    Requires: enable_shared_from_this<T> must be an accessible base class of T. *this must be a subobject of an instance t of type T . There must exist at least one shared_ptr instance p that owns t.
    Au d�but j'avais pris �a pour � l'objet appelant shared_from_this() sur lui-m�me doit �tre hold� par un autre objet via un shared_ptr, n'importe lequel �. En fait, il faut comprendre � l'objet appelant shared_from_this sur lui-m�me doit �tre hold� par un autre objet via un shared_ptr cr�� lui aussi � partir de shared_from_this() �, nuance.
    C'est �a qui garanti que le shared_ptr cr�� par shared_from_this() est persistant, vu qu'une copie partageant le m�me compteur tra�ne dans un autre objet.

    Voil� pourquoi dans la doc de boost (voir le premier lien du post) ils cr�ent leur objet dans une fonction membre statique factory au lieu d'un constructeur (ce que tu fais �galement dans ton article, Lo�c).

    Tout cela explique pourquoi mon code ne fonctionnait pas.
    Si un objet de type directory (reprenons cet exemple) envoie un shared_ptr de lui-m�me (cr�� par shared_from_this) � son item, comme ici� :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
     
    void
    directory::add(std::shared_ptr<directory_item> an_item)
    {
        m_items.push_back(an_item);
        an_item->parent(shared_from_this());
    }
    � et que l'objet de type directory_item store un weak_ptr de son directory parent� :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    class directory_item
    {
        public:
            void
            parent(std::weak_ptr<directory> parent_directory);
     
        private:
            std::weak_ptr<directory> m_parent_directory;
    };
    � �a ne peut pas fonctionner, car d�s que directory_item::parent() a termin� son ex�cution, le shared_ptr cr�� par shared_from_this est d�truit, donc le weak_ptr devient imm�diatement invalide.


    Je poste tout de suite pour ne pas perdre ce long message, j'�diterai pour ajouter des informations r�sultant des quelques essais que je m'apr�te � faire.

    Je ne sais pas si tu avais depuis longtemps compris les choses comme �a, Lo�c, mais je pense qu'un petit encart en plus dans ton article pourrait aider bien des gens.

  8. #8
    Membre confirm�
    Profil pro
    Inscrit en
    F�vrier 2007
    Messages
    142
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2007
    Messages : 142
    Par d�faut
    Aaaaaahh, �a y est, j'ai compris !

    En fait, en th�orie �a devrait marcher, puisque, comme on peut le lire dans la doc de boost :
    Note that you no longer need to manually initialize the weak_ptr member in enable_shared_from_this. Constructing a shared_ptr to impl takes care of that.
    Voil� pourquoi �a ne fonctionne pas en pratique.
    J'ai cr�� mes objets directement avec std::make_shared() :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    std::shared_ptr<directory> new_directory = std::make_shared<directory>(directory_name);
    Cette expression semble �tre, en gros, �quivalente � l'expression ci-dessous, mais en mieux car plus rapide et expression-safe :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    std::shared_ptr<directory> new_directory(new directory(directory_name));
    Sauf que std::make_shared() utilise la move semantic (c'est une pure supposition que je fais ici, mais la suite du raisonnement se tient tellement que �a ne peut �tre que �a), ce qui fait qu'il n'est disponible qu'avec C++0x.
    Or, GCC, notre tr�s cher compilateur ador�, ce petit coquinou, n'impl�mente pour le moment pas totalement les rvalue references. � l'heure o� j'�cris ce message, on peut en effet lire sur cette page que :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    Language Feature                   Proposal   Available in GCC?
    Rvalue references                  N2118      GCC 4.3
        Rvalue references for *this    N2439      No
    No !!
    � mon avis, la fonctionnalit� rvalue references for *this devrait �tre utilis�e par la surcharge/sp�cialisation de std::make_shared() destin�e aux classes h�ritant de std::enable_shared_from_this. Sauf qu'�tant donn� que cette fonctionnalit� n'est pas encore impl�ment�e, cette sp�cialisation n'existe pas encore. R�sultat : le weak_ptr de std::enable_shared_from_this n'est pas initialis�, et on ne peut s'en servir de fa�on transparente, CQFD.

    Finalement, si j'utilise explicitement l'op�rateur new au lieu de std::make_shared(), mon code fonctionne comme pr�vu, sans m�me avoir � se poser de question sur l'impl�mentation de std::enable_shared_from_this.

    Conclusion n�1 : Le dimanche rend intelligent.
    Conclusion n�2 : �a m'apprendra � utiliser une impl�mentation b�ta d'un langage encore sur brouillon


    Merci � toi, Lo�c, pour ton coup de main.

  9. #9
    R�dacteur/Mod�rateur
    Avatar de JolyLoic
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Ao�t 2004
    Messages
    5 463
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 51
    Localisation : France, Yvelines (�le de France)

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

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 5 463
    Par d�faut
    De rien... Et d�sol� de t'avoir oubli� alors que j'avais dit que je regarderais de plus pr�s chez moi...

    J'ai quelques doutes sur ton explication, les R-Value ref dans make_shared ayant pour moi le seul but de faire un perfect forwarding des arguments du constructeur.

    Maintenant, il est vrai que je n'ai pas encore utilis� make_shared, et donc que je ne connais pas bien ses interactions avec shared_from_this. Si j'ai bien compris, tu dis que le code suivant ne marche pas :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class A : enable_shared_from_this<A>
    {
      shared_ptr<A> getIt() {return shared_from_this();}
    };
     
    int main()
    {
      shared_ptr<A> p (make_shared<A>()); //1
      weak_ptr<A> w (p->getIt());
      assert(!w.expired());
    }
    Et que �a marcherait si on rempla�ait 1 par :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
      shared_ptr<A> p (new A); //1
    C'est bien �a ?

    Si oui, c'est bien ce que j'appellerais un bug...
    Ma session aux Microsoft TechDays 2013 : D�velopper en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage � la d�couverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'h�sitez pas � me contacter.

  10. #10
    Membre confirm�
    Profil pro
    Inscrit en
    F�vrier 2007
    Messages
    142
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2007
    Messages : 142
    Par d�faut
    Pas de quoi t'excuser, enfin� tu aurais bien pu ne m�me pas me r�pondre.

    Ouch, j'aurais jamais r�ussi � synth�tiser le probl�me � ce point. Mais oui, c'est exactement �a. J'ai test� le code, et effectivement, l'utilisation de shared_from_this() lance un std::bad_weak_ptr (m�me pas besoin de l'assertion).

  11. #11
    Membre confirm�
    Profil pro
    Inscrit en
    F�vrier 2007
    Messages
    142
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2007
    Messages : 142
    Par d�faut
    http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36949
    C'�tait bien un bug
    Il sera r�solu pour la 4.4.

  12. #12
    Membre �m�rite
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 354
    D�tails du profil
    Informations personnelles :
    �ge : 50
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Par d�faut
    si j'ai bien compris il y a un bug dans GCC libstd++
    mais pourquoi tu n'utilises pas Boost ?

  13. #13
    Membre confirm�
    Profil pro
    Inscrit en
    F�vrier 2007
    Messages
    142
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2007
    Messages : 142
    Par d�faut
    std::make_shared() ne fait pas partie de boost, c'est du C++0x (edit : enfin, je crois�).

    Puis je pr�f�re utiliser la libc++ de C++0x, c'est pour un projet perso donc c'est pas bien probl�matique, et �a permettra de ne pas avoir � modifier le code dans le futur.

  14. #14
    R�dacteur/Mod�rateur
    Avatar de JolyLoic
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Ao�t 2004
    Messages
    5 463
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 51
    Localisation : France, Yvelines (�le de France)

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

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 5 463
    Par d�faut
    Ils en ont ajout� un dans boost 1.36 je crois (en tout cas, je l'ai vu dans le svn). Sur un compilo qui aurait les rvalue reference et les variadic templates, c'est impl�ment� comme la norme, a priori, sur les autres, c'est impl�ment� par approximation.

    Par contre, j'avais cru voir que sur un compilo qui aurait TR1, boost serait un simple forward vers ce compilo (sauf que make_shared n'est pas dans TR1, �a devient un peu sac de n�uds...).

    Donc, pour avoir l'impl�mentation boost, il faudrait un compilo qui aurait les rvalue reference et les variadic templates, mais pas TR1. Est-ce que �a existe ?
    Ma session aux Microsoft TechDays 2013 : D�velopper en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage � la d�couverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'h�sitez pas � me contacter.

  15. #15
    Membre �m�rite
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 354
    D�tails du profil
    Informations personnelles :
    �ge : 50
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Par d�faut
    la norme C++ 0x est vraiment allechante, surtout les rvalues,
    mais quand je pense au nombre d'ann�e necessaire pour pouvoir utiliser les nouvelles fonctionnalit�s ... pfffou j'en ai le vertige.

    bon enfin j'y crois, je ne suis pas d�sesp�r� :-)

  16. #16
    Membre confirm�
    Profil pro
    Inscrit en
    F�vrier 2007
    Messages
    142
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2007
    Messages : 142
    Par d�faut
    Tu peux d'ores et d�j� utiliser les rvalue references avec GCC sous Linux.
    Sous Windows, MingGW-gcc4.3 est en version alpha, alors faut voir.

    Personnellement, utilisant Spirit (pour le projet �voqu� dans ce topic), auto me fait bien envie, aussi.

+ R�pondre � la discussion
Cette discussion est r�solue.

Discussions similaires

  1. R�ponses: 15
    Dernier message: 14/12/2004, 18h01
  2. [FLASH MX2004][AS2] Composition
    Par bolo dans le forum Flash
    R�ponses: 9
    Dernier message: 10/12/2004, 16h53
  3. Aide sur la cr�ation d'un type simple (nom composite)
    Par testeur dans le forum PostgreSQL
    R�ponses: 1
    Dernier message: 06/11/2004, 20h30
  4. cl�s composites
    Par Yuna dans le forum Administration
    R�ponses: 12
    Dernier message: 08/01/2004, 09h14
  5. [WSAD] Composition visuelle d'une applet
    Par schum11 dans le forum Eclipse Java
    R�ponses: 1
    Dernier message: 09/04/2003, 16h19

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