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 :

Going Native 2013 - Stephan Lavavej - Don't help the compiler


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre expérimenté

    Homme Profil pro
    Etudiant
    Inscrit en
    Juillet 2012
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Etudiant
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juillet 2012
    Messages : 108
    Par défaut Going Native 2013 - Stephan Lavavej - Don't help the compiler
    Stephan Lavavej - Don't help the compiler
    GoingNative 2013

    La conférence de Stephan. T. Lavavej (alias S.T.L.) lors des GoingNative 2013 est maintenant disponible en rediffusion :


    Voici un résumé de cette conférence :

    Les lambdas ne sont pas toujours mieux

    Utilisez certains foncteurs plutôt que des lambdas.

    Que pensez-vous de ce code ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sort(v.begin(), v.end(), [] (const Elem& l, const Elem& r) { return l > v; }
    Eh bien, Lavavej explique qu'il est verbeux. En effet, il préconise l'utilisation du foncteur greater dans ce cas là, de la manière suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sort(v.begin(), v.end(), std::greater<Elem>());
    Les foncteurs greaters, plus, multiplies :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    template<class T>
    struct plus {
    T operator()(const T& x, const T& y)
    { return x + y; }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template<class T>
    struct multiplies {
    T operator()(const T& x, const T& y)
    { return x * y; }
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template<class T>
    struct greater {
    bool operator()(const T& x, const T& y)
    { return x > y; }
    };
    À travers ces codes S.T.L. veut nous montrer la simplicité d'utilisation de ces foncteurs par rapport aux lambdas qui sont plus verbeuses. Utiliser certains foncteurs intéressants et utiles (greater, less, plus, multiplies, et d'autres...) permet de gagner grandement en lisibilité.


    Les diamonds

    Au cours de cette conférence, Stephan T. Lavavej a également présenté, un nouveau type de foncteurs, nommés "diamonds" sur lesquels il travaille.

    Il a effectué une proposition pour la standardisation du C++14. Voici un code d'exemple d'utilisation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    vector<const char *> v { "cute", "fluffy", "kittens" };
    set<string, greater<>> s { "Hungry", "EVIL", "ZOMBIES" };
    vector<string> dest;
    transform(v.begin(), v.end(), s.begin(), back_inserter(dest), plus<>());
    Grâce aux codes suivants, avec les conteneurs vector et set, ainsi que l'algorithme transform, Lavavej explique, et prouve leur simplicité d'utilisation, ainsi que leur côté extrêmement pratique.


    En résumé :
    Utilisez les foncteurs "diamonds" lorsqu'ils seront disponibles, cela améliorera la lisibilité.
    En plus d'être moins verbeux, ils sont plus efficaces et permettent d'éviter les divers dangers de conversion de types.


    L'utilité du const X&&

    Dans cette petite partie, S.T.L. nous explique que :

    • const X&& n'est pas utile pour la sémantique de déplacement ;
    • const X&& n'est pas parfait pour le transfert parfait également ;
      Excepté X&& qui déclenche la déduction d'argument d'un template.


    Cependant, const X&& permet de rejeter des temporaires.

    Synthèse générale :
    • Apprenez à utiliser les références rvalues.

    • Ne surchargez pas les transferts parfaits, car ils sont intentionnellement gourmands.

    • Utilisez les temporaires seulement quand ils sont nécessaires.

    • Utilisez "const X&&" pour rejeter les temporaires

    • Mais surtout essayez d'écrire du code uniquement lorsque vous savez comment celui-ci va se comporter. Cela améliore votre conception et réduit le nombre de modifications apportées à votre code par rapport à un développement sans réflexion.

      C'est généralement vrai, mais spécialement pour les références rvalues, sinon veuillez demander, ou vous faire conseiller par un expert.

    • Utilisez certains foncteurs (greater, plus, multiplies, less, etc...), plutôt que les lambdas qui nuisent à la lisibilité.


    Évènement : GoingNative 2013

    Et vous
    Qu'en pensez-vous ?

  2. #2
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 633
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 633
    Par défaut
    Salut,

    Ca me rassure, car je me souviens de quelques débats dans lesquelles je prenais des position similaires.

    Je ne nies absolument pas l'intérêt des expressions lambda, mais je crois que, comme toute nouvelle technique, il est important de se l'approprier et de trouver les cas où elle apporte réellement un plus par rapport à l'existant.

    Le gros intérêt des foncteurs, selon moi (quel que soit le nom qu'on puisse leur donner, du moment qu'ils soient explicites ) est qu'il est possible de les réutiliser bien plus qu'une expression lambda et qu'il y a même moyen de les généraliser si l'on est un peu attentif aux différents concepts mis en oeuvre dans un projet
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    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
    J'avoue en effet être forcé de réécrire assez souvent le même genre de lambdas. La plupart du temps, c'est parce que je dois déréférencer un pointeur dans la comparaison. Une façon d'améliorer ça serait utile.

  4. #4
    Membre expérimenté

    Homme Profil pro
    Etudiant
    Inscrit en
    Juillet 2012
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Etudiant
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juillet 2012
    Messages : 108
    Par défaut
    Citation Envoyé par koala01
    Je ne nies absolument pas l'intérêt des expressions lambda, mais je crois que, comme toute nouvelle technique, il est important de se l'approprier et de trouver les cas où elle apporte réellement un plus par rapport à l'existant.
    Tout à fait d'accord.

    Comme, je disais tout à l'heure a germinolegrand, la vision de lavavej sur les lambdas est je pense une vision que bien du monde devrait avoir.
    A savoir certes elles sont tres pratiques mais dans certains cas, on a des foncteurs qui peuvent faire l'affaire.

    Maintenant le fait est qu'au niveau d'une reutilisation rien ne vaut les foncteurs.

    Cependant je trouve qu'une lambda utilisée avec auto ameliore la lisiblité d'un code.

    C'est d'ailleurs ce que j'essaye de faire en ce moment c'est à dire :
    Favoriser une utilisation des foncteurs, plutot qu'une lambda, dans certains cas comme l' exemple de S.T.L.

  5. #5
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 633
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 633
    Par défaut
    Citation Envoyé par germinolegrand Voir le message
    J'avoue en effet être forcé de réécrire assez souvent le même genre de lambdas. La plupart du temps, c'est parce que je dois déréférencer un pointeur dans la comparaison. Une façon d'améliorer ça serait utile.
    En fait, on en revient toujours au fait qu'il faut avoir une vue "transversale" de son projet : il y a des "concepts" qui apparaissent, de manière générale, dans presque la totalité de tes hiérarchies de classes.

    Mettons que tu travailles sur des objets pour lesquels tu aies décidé de fournir à chaque fois un identifiant unique.

    Tu auras sans doute travaillé correctement en veillant à garder tes hiérarchies clairement distinctes, mais la plupart d'entre elle auront une propriété commune : une fonction id() (ou getId() ou ce que tu veux) qui renvoie l'identifiant unique de l'objet en question

    Le fait est que cet identifiant unique est un très bon candidat pour les tentatives de classement, et que tu vas donc sans doute régulièrement utiliser une lambda pour vérifier quel identifiant est plus petit que l'autre (dans une même game d'objets, s'entend)

    Dés lors, pourquoi ne pas créer un foncteur spécial sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    template <typename T>
    struct lessById{
        bool operator()(T const & first, T const & second) const{
            return first.id() < second.id();
        }
        /* comme cela, on prend les pointeurs en compte également ;) */
        bool operator()(T * first, T * second) const{
            return this->(*first, *second);
        }
    };
    Tu l'écris une fois, tu l'utilises partout où tu en as besoin

    Puis, tu en viens à te rendre compte que pas mal de tes hiérarchies présente le concept de "positionnable" et que tu tries souvent des objets en fonction de la position à laquelle ils se trouvent.

    Hé bien, c'est reparti : on crée un autre foncteur qui pourrait être proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    template <typename T>
    struct lessByPosition{
        bool operator()(T const & first, T const & second) const{
            return first.position().x() < second.position().x() ||
                     ( first.position.x() == second.position.x() &&
                       first.position.y() < second.position.y() );
        }
        /* comme cela, on prend les pointeurs en compte également ;) */
        bool operator()(T * first, T * second) const{
            return this->(*first, *second);
        }
    };
    ET ainsi de suite pour chaque concept plus ou moins transversal

    Maintenant, il n'y a strictement rien qui ne t'empêche de faire pareil pour un concept qui ne serait utilisé que pour un certain type bien particulier pour lequel les comparaisons sont fréquentes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void lessBySomething{
        bool operator()(SomeType const & first, SomeType const & second) const{
            /* the correct logic to use */
    }
        bool operator()(SomeType  * first, SomeType  * second) const{
            return this->(*first, *second);
        }
    };
    Ce qui importe, c'est qu'au lieu de copier sans cesse tes labmda (qui sont effectivement particulièrement verbeuses), tu te retrouve avec une seule "version" du code, qui se trouve à un endroit bien déterminé dans ton projet, et que, si tu dois en corriger la logique, tu n'auras qu'un seul endroit du code à vérifier.

    Les expressions lambda devraient, au final, être réservées à des situations dont on a la certitude qu'elles ne serviront qu'à cet endroit bien particulier
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #6
    Inactif
    Inscrit en
    Août 2013
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Août 2013
    Messages : 27
    Par défaut
    Au final, c'est juste un rappel des règles existantes (factoriser son code, utiliser l'existant), rien de nouveau. C'est juste que les gens oublient souvent ces règles de base (@germinolegrand non non, je vise personne... tu en es où avec l'écriture de ta lib de GUI ? )

  7. #7
    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
    Fort heureusement mes lambdas sont toujours assez courtes et simples pour qu'il soit plus rapide/facile de les écrire sans aller voir ailleurs ^^ (vite écrit quand on a le coup de main ).

    Ce sont les foncteurs diamonds qui sont intéressants parce qu'ils nous offrent dores et déjà des foncteurs polymorphiques .

    Et justement, ils risquent de m'aider pour la GUI sur laquelle je travaille actuellement (qui n'a rien à voir avec la GUI entièrement basée sur les std::function que j'ai laissée tomber bien que résolvant tous les problèmes de mise à jour de valeurs dynamiques). Je me retrouve avec des macros parce que je ne pouvais pas passer des fonction template en tant que foncteur... ce que vise à résoudre cette technique pour laquelle je remercie S.T.L. d'en avoir montré les ficelles .

Discussions similaires

  1. Réponses: 0
    Dernier message: 15/10/2010, 14h25
  2. Don't flush the Session after an exception occurs
    Par yohan_al dans le forum Hibernate
    Réponses: 1
    Dernier message: 31/03/2009, 15h57
  3. Réponses: 2
    Dernier message: 23/01/2008, 16h26

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