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

Langage C++ Discussion :

variadic functions sans stdarg ?


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre très actif

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Par défaut variadic functions sans stdarg ?
    Bonjour tout le monde,

    voilà je me remet au C++ après des années de sommeil

    J'étais en train de faire des tests sur des variadic templates et je me suis demandé s'il y avait possibilité d'itérer plus "modernement" sur la liste des arguments d'une variadic function qu'avec les fonctions de la SL :

    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
     
    #include <vector>
     
    template <class T>
    class A
    {
        private :
            std::vector<T> v;
     
        public :
            A(T& ts...);       
    };
     
    template <class T>
    A<T>::A(T& ts...)
    {
        std::vector<T> temp = { ts... };
        for (auto t : temp)
            v.push_back(t);
    }
    Le compilateur me répond que je fais une mauvaise utilisation de "ts..." car, je cite :

    ||=== Build: Debug in POO (compiler: GNU GCC Compiler) ===|
    POO\main.cpp||In constructor 'A<T>::A(T&, ...)': |
    POO\main.cpp|32|error: expansion pattern 'ts' contains no argument packs|
    POO\main.cpp||In instantiation of 'A<T>::A(T&, ...) [with T = int]': |
    POO\main.cpp|40|required from here|
    main.cpp|32|error: could not convert '{<expression error>}' from '<brace-enclosed initializer list>' to 'std::vector<int, std::allocator<int> >'|
    ||=== Build failed: 2 error(s), 2 warning(s) (0 minute(s), 0 second(s)) ===|
    N'y a-t'il pas une manière plus ou moins aussi élégante de parcourir ce type de liste ?

    Merci d'avance

  2. #2
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 513
    Par défaut
    Bonjour,

    Un code équivalent qui compile et fonctionne :
    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
    #include <vector>
     
    template<class T>
    class A
    {
        private :
            std::vector<T> v;
     
        public :
            template<class... Args>
            A(Args&&... args);       
    };
     
    template<class T>
    template<class... Args>
    A<T>::A(Args&&... args)
    {
        std::vector<T> temp = { std::forward<Args>(args)... };
        for(auto& t : temp)
            v.push_back(t);
    }
    Cela dit, il est inutile de créer un vecteur temporaire. Il vaut mieux écrire directement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template<class T>
    template<class... Args>
    A<T>::A(Args&&... args) :
        v({ std::forward<Args>(args)... })
    {
    }
    Concernant les parameter packs, tu trouveras tous les détails ici : http://en.cppreference.com/w/cpp/lan...parameter_pack

  3. #3
    Membre très actif

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Par défaut
    oui pour le temp c'était à force de tenter des écritures pour voir d'où venait le problème.

    Merci pour les infos.

  4. #4
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    A quoi sert le std::forward dans ce code ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template<class T>
    template<class... Args>
    A<T>::A(Args&&... args) :
        v({ std::forward<Args>(args)... })
    {
    }
    J'ai l'impression que ça fonctionne très bien sans. Merci

  5. #5
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 513
    Par défaut
    Citation Envoyé par Bktero Voir le message
    A quoi sert le std::forward dans ce code ?
    C'est pour éviter des copies inutiles dans le cas où des arguments sont des rvalues. Si tu essaies 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
    struct Test
    {
        Test() = default;
        Test(const Test&) {std::cout << "copie ";}
        Test(Test&&)      {std::cout << "deplacement ";}
    };
     
    int main()
    {
    	A<Test> monTest(Test{});
    	return 0;
    }
    Sans le std::forward, ça devrait t'afficher "copie copie". Avec le std::forward, ça devrait t'afficher "deplacement copie".

    De manière générale, voici un lien qui explique bien le fonctionnement et l'intérêt de std::forward :
    http://stackoverflow.com/questions/3...582313#3582313

  6. #6
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    Bon... Je ne vois déjà pas où est appelé la première fois le constructeur par copie. cppreference m'a fait comprendre que Test {} provoque un appel au constructeur par copie, std::forward provoque l'appel au constructeur par déplacement. Quand je lis A(Args&&... args); et notamment le &&, dois-je comprendre que c'est un constructeur par déplacement ou pas du tout ?

    Pourquoi est-ce que le code suivant ne fait pas appel au constructeur par déplacement ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int main()
    {
        Test test = Test { };
        A<Test> monTest(test);
        return 0;
    }
    Je m'en vais potasser ton lien

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

Discussions similaires

  1. printf sans stdarg.h
    Par lwhite dans le forum Débuter
    Réponses: 4
    Dernier message: 06/11/2008, 18h14
  2. Function sans Return
    Par Danyel dans le forum VB.NET
    Réponses: 5
    Dernier message: 02/05/2008, 17h10
  3. Réponses: 2
    Dernier message: 31/03/2008, 17h53
  4. Réponses: 3
    Dernier message: 28/09/2007, 11h44
  5. transport tablespace sans view function et package
    Par debdba dans le forum Administration
    Réponses: 13
    Dernier message: 25/06/2007, 11h58

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