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 :

Exercice C++ : des push_back transactionnels [Débat]


Sujet :

C++

  1. #41
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    371
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 371
    Par défaut
    Citation Envoyé par germinolegrand Voir le message
    pour compter la taille d'un variadic, il y a l'operateur sizeof...()
    Ça aide Merci pour l'info !

    Citation Envoyé par germinolegrand Voir le message
    là tes conteneurs sont aussi déplacés (vous confirmez ?).
    Il semblerait que non, cf. le code suivant.
    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
    struct C {
        std::vector<int> v;
        C() { std::cout << "C()" << std::endl; }
        C(const C& c) : v(c.v) { std::cout << "C(const C&)" << std::endl; }
        C(C&& c) : v(std::move(c.v)) { std::cout << "C(C&&)" << std::endl; }
     
        void insert(std::vector<int>::iterator iter, int&& i) {
            v.insert(iter, std::move(i));
        }
        void insert(std::vector<int>::iterator iter, const int& i) {
            v.insert(iter, i);
        }
        void erase(std::vector<int>::iterator iter) {
            v.erase(iter);
        }
        std::vector<int>::iterator end() { return v.end(); }
    };
     
    int main() {
        C va;
        safePushBack(va, 1, va, 2);
        std::cout << va.v.size() << std::endl;
    }
    ... qui affiche :
    C()
    2
    Par contre j'ai fait une erreur. Il ne faut pas utiliser std::move mais std::forward, sinon on déplace toujours les objets (même quand l'utilisateur donne une l-value) :
    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
    template <class C, class T>
    static inline void safePushBack(C& cont, T&& i)
    {
        cont.insert(std::end(cont), std::forward<T>(i));
    }
     
    template <class C, class T, class ... Args>
    static inline void safePushBack(C& cont, T&& i, Args&&... args)
    {
        cont.insert(std::end(cont), std::forward<T>(i));
        try
        {
            safePushBack(std::forward<Args>(args)...);
        }
        catch(...)
        {
            cont.erase(std::end(cont));
            throw;
        }
    }

  2. #42
    Membre Expert

    Avatar de germinolegrand
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2010
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2010
    Messages : 738
    Par défaut
    Ah oui ^^ c'est surtout pour le std::move que je me disais que ça bougeait tout ^^
    Mais std::forward sur une r-value, ça fais bien un move non ?

  3. #43
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    371
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 371
    Par défaut
    std::move transforme son argument en r-value, quel qu'il soit. Donc là oui : si on utilise std::move partout, les conteneurs et les objets stockés sont déplacés, ce qui peut créer son lot de surprises.

    Par contre std::forward garde les l-values comme des l-values, et les r-values comme des r-values. Donc oui, std::forward sur une r-value c'est comme std::move, mais sur une l-value ça ne fait rien. Maintenant, la signature de la fonction est trompeuse... On pourrait croire que, comme les arguments sont déclarés comme étant de type Args&& ..., ce sont tous des r-values. Mais ce n'est pas le cas. Un exemple simplifié :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    template<typename T>
    void foo(T&& t);
    Si on appelle foo avec comme argument une l-value U u;, alors dans foo(u), u est d'abord interprété comme étant de type T == U&, et la règle (spécifique au cas template) est alors (U&)&& == U& : l'argument n'est pas du tout une r-value... Et c'est grâce à ça que std::forward fonctionne.

    En revanche, si on appelle foo avec comme argument une r-value, on a deux possibilités :
    • foo(U()) : on a T == U, et la règle est triviale : (U)&& == U&&,
    • foo(std::move(u)) : on a T == U&&, et la règle est : (U&&)&& == U&&.

    (source : open-std.org)

    En résumé dans ce genre de situation :
    • si on utilise std::move, tout est déplacé (ça peut être grave et contre-intuitif si pas documenté),
    • si on n'utilise rien, les r-values qui auraient pu être déplacées seront copiées (c'est dommage),
    • si on utilise std::forward, ce qui peut être déplacé sans conséquence (les r-values) est déplacé, et ce qui n'a pas raison de l'être (les l-values) ne l'est pas.

Discussions similaires

  1. Exercice - Gestion des employés d'une banque
    Par Adnane-Xx dans le forum C
    Réponses: 2
    Dernier message: 03/06/2014, 18h00
  2. [sh] Exercice concaténation des lignes impaires d'un fichier
    Par ettar dans le forum Shell et commandes GNU
    Réponses: 6
    Dernier message: 29/05/2014, 14h02
  3. créer des feuilles d'exercices avec des corrigés
    Par Dexter80 dans le forum Mise en forme
    Réponses: 5
    Dernier message: 22/08/2012, 19h10
  4. exercice théorie des langages
    Par abdellah 1 dans le forum Algorithmes et structures de données
    Réponses: 1
    Dernier message: 18/04/2009, 01h14
  5. Réponses: 4
    Dernier message: 27/02/2005, 22h43

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