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 :

Perfect forwarding d'un vecteur de unique_ptr ?


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de Seabirds
    Homme Profil pro
    Post-doctoral fellow
    Inscrit en
    Avril 2015
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Post-doctoral fellow
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2015
    Messages : 294
    Par défaut Perfect forwarding d'un vecteur de unique_ptr ?
    Salut à tous et à toutes !

    J'ai pour représentaire un arbre n-aire, une classe Node qui a a priori sémantique d'entité. Histoire d'essayer de gérer la propriété des noeuds correctement, j'ai utilisé un vector de unique_ptr pour représenter les enfants (choix peut être contestable).
    Pour construire un arbre à partir des feuilles, j'aimerais écrire ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    	auto f = make_node<int>(5);
    	auto g = make_node<int>(6);
     
    	std::vector<std::unique_ptr<Node<int>>> children;
    	children.push_back(std::move(f));
    	children.push_back(std::move(g));
     
    	auto e = make_parent<int>(children, 4); // là le compilateur me dit que je parle assez mal le c++
    	assert( (!f.get()) && !g.get()); // unique_ptr are now empty
    Le compilateur me dit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    error: no matching function for call to ‘make_parent(std::vector<std::unique_ptr<Node<int>, std::default_delete<Node<int> > >, std::allocator<std::unique_ptr<Node<int>, std::default_delete<Node<int> > > > >&, int)auto e = make_parent<int>(children, 4);
    Donc je me dis que j'ai foiré en essayant d'éviter la copie du vector dans la fonction friend make_parent:

    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
     
    template<typename T>
    class Node;
     
    template<typename T, typename ...Args>
    std::unique_ptr<Node<T>> make_node(Args&& ...args);
     
    template<typename T, typename ...Args>
    std::unique_ptr<Node<T>> make_parent(std::vector<std::unique_ptr<Node<T>>>&& children, Args&& ...args);
     
    template<typename T>
    class Node{
         // ...
    private:
        Node() = default;
        Node(const Node&) = delete;
        Node& operator=(const Node&) = delete;
     
        template <typename... Args>
        Node(Args&&... args ) : m_data(T(std::forward<Args>(args)...)) {}
     
        template <typename ...Args>
        friend std::unique_ptr<Node<T>> make_node(Args&& ...args){
        	return std::unique_ptr<Node<T>>(new Node<T>(std::forward<Args>(args)...));
        }
     
        template<typename ...Args>
        friend std::unique_ptr<Node<T>> make_parent(std::vector<std::unique_ptr<Node<T>>>&& children, Args&& ...args){
            std::unique_ptr<Node<T>> ptr = std::make_unique<Node<T>>(new Node<T>(std::forward<std::vector<std::unique_ptr<Node<T>>>>(children), std::forward<Args>(args)...));
    	for(auto & it : children){
    	     it->m_parent = ptr.get();
    	     ptr->m_children.push_back(std::move(it));
            }
            return ptr;
        }
     
        Node<T>* m_parent = nullptr; // inexistence possible
        std::vector<std::unique_ptr<Node<T>>> m_children;
        T m_data;
    };
    J'y suis depuis hier matin, et j'ai lu plein de trucs intéressants sur stack overflow à propos de templates, des friends, des universal references, mais je manque de pratique en la matière (et je ne pourrai pas prétendre avoir tout compris à la théorie des && ). Malgré mes tentatives d'écrire la même chose de différentes façon, je ne comprends pas ce que j'ai mal fait, pourriez-vous me l'indiquer je vous prie ?
    En vous remerciant,

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 153
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 153
    Billets dans le blog
    4
    Par défaut
    Hello,

    peut-être pas la solution mais as-tu essayé auto e = make_parent<int>(std::move(children), 4); ?
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Membre éclairé Avatar de Seabirds
    Homme Profil pro
    Post-doctoral fellow
    Inscrit en
    Avril 2015
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Post-doctoral fellow
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2015
    Messages : 294
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Hello,

    peut-être pas la solution mais as-tu essayé auto e = make_parent<int>(std::move(children), 4); ?
    bonjour Bousk ! Oui, j'ai essayé, c'est d'ailleurs le message d'erreur de trop qui m'a fait aller chercher votre aide Je ne sais en effet pas ce qu'est une "expression list treated as compound expression in functional cast error". Et google est assez peu bavard à ce sujet :/

    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
    Node.h: In instantiation of ‘Node<T>::Node(Args&& ...) [with Args = {std::vector<std::unique_ptr<Node<int>, std::default_delete<Node<int> > >, std::allocator<std::unique_ptr<Node<int>, std::default_delete<Node<int> > > > >, int}; T = int]’:
    Node.h:116:62:   required from ‘std::unique_ptr<Node<T> > make_parent(std::vector<std::unique_ptr<Node<T> > >&&, Args&& ...) [with Args = {int}; T = int]’
    Node_test.cpp:56:50:   required from here
    Node.h:107:66: error: expression list treated as compound expression in functional cast [-fpermissive]
         Node(Args&&... args ) : m_data(T(std::forward<Args>(args)...)) {}
                                                                      ^
    /usr/include/c++/5/bits/unique_ptr.h: In instantiation of ‘typename std::_MakeUniq<_Tp>::__single_object std::make_unique(_Args&& ...) [with _Tp = Node<int>; _Args = {Node<int>*}; typename std::_MakeUniq<_Tp>::__single_object = std::unique_ptr<Node<int>, std::default_delete<Node<int> > >]’:
    Node.h:116:62:   required from ‘std::unique_ptr<Node<T> > make_parent(std::vector<std::unique_ptr<Node<T> > >&&, Args&& ...) [with Args = {int}; T = int]’
    Node_test.cpp:56:50:   required from here
    Node.h:107:5: error: ‘Node<T>::Node(Args&& ...) [with Args = {Node<int>*}; T = int]’ is private
         Node(Args&&... args ) : m_data(T(std::forward<Args>(args)...)) {}
         ^
    In file included from /usr/include/c++/5/memory:81:0,
                     from Node.h:17,
                     from Node_test.cpp:13:
    /usr/include/c++/5/bits/unique_ptr.h:765:69: error: within this context
         { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 153
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 153
    Billets dans le blog
    4
    Par défaut
    Commence par faire un truc simple, parce qu'à priori tu pars dans tous les sens et c'est difficilement lisible.
    Tu crées un node et tu ajoutes des children, make_parent c'est de la fioriture par-dessus.

    Cette ligne me parait suspecte
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::unique_ptr<Node<T>> ptr = std::make_unique<Node<T>>(new Node<T>(std::forward<std::vector<std::unique_ptr<Node<T>>>>(children), std::forward<Args>(args)...));
    Pourquoi ce n'est pas un std::move ? Et où se trouve le constructeur pour ça ? Je ne vois qu'un constructeur pour les T args..., en aucun cas les children (ce qui est logique).
    Et ton parcours qui suit est faux, si tu mouves le vector, tu parcourras un vector vide, il devra devenir for(auto & it : m_children){
    La création d'un Node, devrait être simple, parent ou pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    auto node = make_node...
    m_children = std::move(children);
    for (auto& child : m_children) child->parent = this;
    Si par la suite tu veux mettre ça dans un make_parent, ça n'y changera rien.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Membre éclairé Avatar de Seabirds
    Homme Profil pro
    Post-doctoral fellow
    Inscrit en
    Avril 2015
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Post-doctoral fellow
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2015
    Messages : 294
    Par défaut
    Merci pour tes conseils, je fais ça (j'avais déjà un truc qui fonctionnait pour ajouter les enfants un à un, du coup je voulais factoriser un peu, mais si c'est une mauvaise idée... )

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 153
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 153
    Billets dans le blog
    4
    Par défaut
    Je n'ai pas l'impression que tu aies saisi mon message.
    Que donne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    std::unique_ptr<Node<T>> make_parent(std::vector<std::unique_ptr<Node<T>>>&& children, Args&& ...args){
            std::unique_ptr<Node<T>> ptr = std::make_unique<Node<T>>(new Node<T>(std::forward<Args>(args)...));
            ptr->m_children = std::move(children);
    	for(auto & it : ptr->m_children){
    	     it->m_parent = ptr.get();
            }
            return ptr;
        }
    ?
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

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

Discussions similaires

  1. Packet forwarder
    Par Gabuzomeu dans le forum Développement
    Réponses: 3
    Dernier message: 03/06/2003, 17h44
  2. Zoom sur des vecteurs ou lignes
    Par mat.M dans le forum Algorithmes et structures de données
    Réponses: 7
    Dernier message: 25/11/2002, 10h40
  3. Ports forwarding avec iptables
    Par Iced Earth dans le forum Réseau
    Réponses: 6
    Dernier message: 19/11/2002, 21h24
  4. matrices * vecteur
    Par delire8 dans le forum Algorithmes et structures de données
    Réponses: 15
    Dernier message: 07/09/2002, 14h15

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