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 :

généralisation du std::swap à n paramètres


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Par défaut généralisation du std::swap à n paramètres
    Bonjour

    Voici une implémentation possible du std::swap que nous connaissons tous.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template<class T>
    void swap(T & l, T & r)
    {	T tmp = std::move(l);
    	l = std::move(r);
    	r = std::move(tmp);
    }
    Et voici le principe de sa généralisation à n paramètres.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    template<class T>
    void multiple_swap(T & v0, T & v1, ..., T & vn)
    {	T tmp = std::move(v0);
    	v0 = std::move(v1);
    	v1 = ...;
    	... = vn;
    	vn = std::move(tmp);
    }
    Existe-t-il en standard ? (pas à ma connaissance)
    Une idée d'implémentation généralisée ?
    Pour certains algos il serait utile je pense, car pour l'instant il m'arrive d'appeler le swap standard en cascade, ce qui induit des copies évitables.

    Merci

  2. #2
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    29
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 29
    Par défaut
    Ce n'est plus vraiment un swap, mais plutôt une rotation.

    Si tu peux mettre tes variables dans un container, tu faire appel à std::rotate qui fait le job : il utilise des swap en interne.

    Sinon, ça doit pouvoir se faire avec du parameter-pack.

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    29
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 29
    Par défaut
    Voici avec le parameter-pack, enjoy.

    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
     
    #include <iostream>
    #include <string>
     
    template<typename T>
    T & rotation_detail(T & elt, T & last)
    {
        elt = std::move(last);
        return last;
    }
     
    template<typename T, typename ... Args>
    T & rotation_detail(T & elt, T & elt2, Args & ... args)
    {
        elt = std::move(elt2);
        return rotation_detail(elt2, args...);
    }
     
    template<typename T, typename ... Args>
    void rotation(T & elt, Args & ... args)
    {
        T tmp = elt;
        T & last = rotation_detail(elt, args...);
        last = std::move(tmp);
    }
     
    int main()
    {
        std::string a = "a";
        std::string b = "b";
        std::string c = "c";
        std::string d = "d";
        std::string e = "e";
     
        std::cout << a << b << c << d << e << std::endl;
     
        rotation(a, b, c, d, e);
     
        std::cout << a << b << c << d << e << std::endl;
    }
    Le lien vers coliru.

    Après, on pourrait déplacer les rotation_detail dans des namespaces details et ajouter un check sur les types pour éviter un message de compilation obscure, voir ce lien stackoverflow.

  4. #4
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 760
    Par défaut
    Je propose cette version:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    template<class T, class... Ts>
    void rotate(T& x, Ts& ... xs)
    {
        T tmp = std::move(x);
        [&](auto&... lhs){
            [&lhs...](auto&... rhs){
                (void(lhs = std::move(rhs)), ...);
            }(xs..., tmp);
        }(x, xs...);
    }
    => https://wandbox.org/permlink/ccEMBfqXOwmFysfK

    Qui au passage soulève un bug dans clang: il faut mettre lhs... pour que cela compile, et avec il y a un avertissement comme quoi lhs n'est pas utilisé (mais tout passe bien).

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    29
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 29
    Par défaut
    Pas mal l'astuce du double lambda pour le décalage, je plussoie !

  6. #6
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 760
    Par défaut
    Je me suis rendu compte après coup qu'on peut faire simplement std::tie(x, xs...) = std::forward_as_tuple(std::move(xs)..., std::move(tmp));.

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

Discussions similaires

  1. Passage de std::pair en paramètre fail !
    Par Captain'Flam dans le forum Débuter
    Réponses: 4
    Dernier message: 03/04/2014, 21h42
  2. Réponses: 4
    Dernier message: 03/04/2011, 20h14
  3. Passage de std::string en paramètre
    Par Keweed dans le forum Débuter
    Réponses: 11
    Dernier message: 31/10/2009, 10h22
  4. Réponses: 1
    Dernier message: 09/07/2008, 15h54

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