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 :

Guru Of the Week n° 41 : utiliser la bibliothèque standard


Sujet :

C++

  1. #1
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut Guru Of the Week n° 41 : utiliser la bibliothèque standard
    La bibliothèque standard fournit un nombre important de structures de données et d'algorithmes. Dans de nombreux cas, il est possible de remplacer les structures de contrôle du langage (if, for, while) par les fonctionnalités provenant de celle-ci. Dans ce Guru Of the Week n° 41, Herb Sutter lance le défi de créer un Mastermind en minimisant l'utilisation des structures de contrôle.

    Guru Of the Week n° 41 : utiliser la bibliothèque standard

    Saurez-vous relever le défi et proposer un tel code de Mastermind ?

    Retrouver l'ensemble des Guru of the Week sur la page d'index.

  2. #2
    Membre éprouvé
    Avatar de mitkl
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2010
    Messages
    364
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2010
    Messages : 364
    Points : 1 081
    Points
    1 081
    Par défaut
    La solution est très intéressante, c'est une approche que je n'avais jamais développé, j'aime beaucoup !

    Citation Envoyé par gbdivers Voir le message
    Saurez-vous relever le défi et proposer un tel code de Mastermind ?
    Honnêtement quand j'ai lu l'énoncé, faire un mastermind sans aucun if/for/while me semblait difficilement réalisable. Après avoir vu la solution, j'ai eu quelques déclics avec l'utilisation de la STL et ça me semble déjà plus réalise.
    Si vous ne savez toujours pas ce qu’est la récursivité, relisez cette phrase.

    Mon blog sur la programmation et l'informatique !

  3. #3
    Membre éclairé

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

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Points : 764
    Points
    764
    Par défaut
    Il manque un lien vers l'article original

    Sinon je trouve dommage que l'exemple de code fourni soit si inutilement cryptique. Ça nuit à la compréhension de l'article, et ça ne fait pas envie (et encore, la mise en forme choisie sur Developpez est un peu plus claire grâce aux sauts de lignes).

  4. #4
    Expert éminent
    Avatar de transgohan
    Homme Profil pro
    Développeur Temps réel Embarqué
    Inscrit en
    Janvier 2011
    Messages
    3 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Temps réel Embarqué

    Informations forums :
    Inscription : Janvier 2011
    Messages : 3 146
    Points : 9 386
    Points
    9 386
    Par défaut
    Je suis pas très calé en c++ mais je vois pas tellement l'intérêt du défi.
    Le but est de n'utiliser que la STL c'est ça ? (après faut bien avouer qu'elle est sous-utilisée - et je me compte dedans xD )
    Car au final, il est faux de dire qu'on n'utilise aucun test et boucle.

    « Toujours se souvenir que la majorité des ennuis viennent de l'espace occupé entre la chaise et l'écran de l'ordinateur. »
    « Le watchdog aboie, les tests passent »

  5. #5
    Membre éprouvé
    Avatar de mitkl
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2010
    Messages
    364
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2010
    Messages : 364
    Points : 1 081
    Points
    1 081
    Par défaut
    Le but est d'utiliser le moins possible d'if/for/while, c'est un GotW qui fait réfléchir, ça ne veut pas dire qu'il ne faut plus utiliser de structure de contrôle mais au lieu d'imbriquer des if dans des for et compagnie, un petit coup de STL, un foncteur peuvent être plus lisibles.
    Si vous ne savez toujours pas ce qu’est la récursivité, relisez cette phrase.

    Mon blog sur la programmation et l'informatique !

  6. #6
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Citation Envoyé par Kalith Voir le message
    Sinon je trouve dommage que l'exemple de code fourni soit si inutilement cryptique. Ça nuit à la compréhension de l'article, et ça ne fait pas envie
    +1
    Quelle catastrophe ce code... Je ne parle pas de l'utilisation un peu extrême de la STL, qui est après tout le but de l'exercice, mais du reste.
    • Nom de variable courte et cryptique. En quelques lignes on subit du l, M, cm, gm, c, g...
    • Utilisation à outrance de l'opérateur virgule. Sérieux il faut emprisonner le dingo qui s'amuse à écrire des lignes du style return ++cm_[c], ++gm_[toupper(g)], exact_ += c == toupper(g), '.';


    Du reste je crois que bien que le code est buggé. En tout cas chez moi, à chaque nouvel tentative l'affichage du nombre de couleurs correctement devinées est faux car vaut toujours zéro. Par contre l'affichage du nombre de couleurs correctement devinées et bien placées vaut le résultat attendu.

    J'ai l'impression que le problème vient d'ici :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::transform( comb.begin(), comb.end(), guess.begin(), l.begin(), Count( color, exact ) );
    Sachant que le destructeur de Count effectue des opérations assez complexes (mise à jour de std::map), j'ai l'impression que le code se base sur des détails d'implémentation en supposant que Count sera copié une fois et détruit une fois dans le std::transform mais manque de bol ce n'est pas le cas sur mon compilo.

  7. #7
    Membre éclairé

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

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Points : 764
    Points
    764
    Par défaut
    J'utilise GCC 4.7 sans activer le C++11 (donc pas de sémantique de mouvement, mais le GotW a été écrit avant la sortie de la norme) et sans optimisation, et ça marche correctement chez moi.

    Sinon je rejoins ta critique : la ligne qui m'a fait le plus mal aux yeux est celle que tu as cité.

  8. #8
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2012
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2012
    Messages : 21
    Points : 58
    Points
    58
    Par défaut
    Salut,

    Citation Envoyé par Arzar Voir le message
    Utilisation à outrance de l'opérateur virgule. Sérieux il faut emprisonner le dingo qui s'amuse à écrire des lignes du style
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return ++cm_[c], ++gm_[toupper(g)], exact_ += c == toupper(g), '.';
    D'ailleurs quelqu'un peut expliquer cette ligne parce que j'ai un peu de mal à voir ce qui est véritablement retourné finalement ?

  9. #9
    Membre éclairé

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

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Points : 764
    Points
    764
    Par défaut
    Seulement le dernier élément, soit ".".
    L'intérêt est de tout écrire en "une instruction", ce qui n'apporte rien en terme de performance, mais peut économiser de la place en terme de quantité de code (c'est discutable ici).

  10. #10
    Membre régulier
    Homme Profil pro
    Ingénieur
    Inscrit en
    Octobre 2006
    Messages
    48
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Transports

    Informations forums :
    Inscription : Octobre 2006
    Messages : 48
    Points : 97
    Points
    97
    Par défaut
    Grosse déception. Un code "sale" non commenté. Voila qui motive le lecteur a créer sa "propre" solution.

  11. #11
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Je viens de vérifier et le code est effectivement buggé. Il ne marche que si le destructeur du foncteur Count n'est appelé qu'une seule fois dans std::transform, ce qui est effectivement le cas avec gcc 4.7 (car le foncteur n'est copié qu'une fois), mais ce qui n'est pas le cas avec visual studio (où std::transform appelle une fonction helper interne qui copie plusieurs fois le foncteur)

    Du coup, ce n'est pas de chance, mais ce code contrevient là aussi aux bonnes pratiques, en particulier :

    1) Ne pas implémenter de logique complexe dans un destructeur.
    Un destructeur est fait pour nettoyer/libérer des ressources, il n'est pas là pour être le cœur d'un algorithme dans lequel on parcourt et mets à jour des structures complexes.

    2) Ne jamais présager de l'utilisation d'un foncteur par la STL. La règle générale c'est que la STL a le droit de faire ce qu'elle veut d'un foncteur passé à un algo, en particulier elle a le droit de le copier autant de fois que nécessaire.

    Edit :
    Humm, j'ai l'impression que le bug est en fait un peu plus subtil que ça.
    En tout cas si ça marche sous GCC c'est clairement grâce à une optimisation (faite même en debug) qui permet d'éliminer toute copie du foncteur. Il n'y a qu'une seule construction et destruction, du coup on s'assure de toujours bien travailler sur les deux maps membres M cm_, gm_; de la structure Count. Par contre avec VS on a des copies et plusieurs destruction (et le nombre est différent entre le mode debug et release), du coup je n'arrive pas bien à suivre ce qui se passe mais on fini par manipuler une map systématiquement vide...

  12. #12
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2011
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Service public

    Informations forums :
    Inscription : Décembre 2011
    Messages : 54
    Points : 67
    Points
    67
    Par défaut
    Je me joins à l'avis général sur la qualité du code... Devoir relire une trentaine de lignes de code plusieurs fois pour les comprendre, gloups.
    En effet, cette ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return ++cm_[c], ++gm_[toupper(g)], exact_ += c == toupper(g), '.';
    et en particulier
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    exact_ += c == toupper(g)
    m'a donné des boutons... Ajouter à un int le résultat d'une comparaison, aïe. Quitte à écrire un code imbitable, un opérateur ternaire pour retourner 0 si false sinon 1 aurait été plus propre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    exact_ += ((c == toupper(g)) == false ? 0 : 1)
    Bref, oui, le problème est solutionné, mais ça sera pas un 20/20!

  13. #13
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 113
    Points : 32 951
    Points
    32 951
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par vravier Voir le message
    Ajouter à un int le résultat d'une comparaison, aïe. Quitte à écrire un code imbitable, un opérateur ternaire pour retourner 0 si false sinon 1 aurait été plus propre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    exact_ += ((c == toupper(g)) == false ? 0 : 1)
    Bref, oui, le problème est solutionné, mais ça sera pas un 20/20!
    Question de point de vue, mais le type bool existe bien en C++ et est considéré comme un entier pouvant prendre 2 valeurs, 0 pour faux ou 1 pour vrai. Les transtypages sont implicites et fonctionnent, c'est correctement normé (par rapport au C à ce niveau).
    cf le prochain curriculum low level.

    Ca peut sembler à moitié de l'obfuscation, mais c'est correct.
    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.

  14. #14
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2011
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Service public

    Informations forums :
    Inscription : Décembre 2011
    Messages : 54
    Points : 67
    Points
    67
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Ca peut sembler à moitié de l'obfuscation, mais c'est correct.
    Bien sur c'est correct, mais comme beaucoup d'autres choses en C/C++, c'est pas parce que ça peut se faire, que c'est forcément bien de le faire
    Sur ce point bien particulier, je trouve juste que ça clarifie en écrivant concrètement ce que ça doit faire. Comme par exemple la fonction GetCheck() sur les checkbox de la MFC qui retourne 0, 1 ou 2 (pas cochée, cochée, à moitié cochée), et qu'on veut en récupérer un booléen, je préfère écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bool value = dialog.GetCheck() != 0;
    plutot que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bool value = dialog.GetCheck();
    Les 2 sont corrects et compilent, c'est juste une question d'appréciation personnelle

  15. #15
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 113
    Points : 32 951
    Points
    32 951
    Billets dans le blog
    4
    Par défaut
    Sauf que ton exemple est à l'envers.
    Tu veux juste transformer une information entière en bool.
    L'exemple du GotW fait l'inverse : il transforme un bool en entier. Et là il n'y a pas besoin de fiorutire, ni d'opérateur ternaire, la conversion est implicite en C++.
    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.

  16. #16
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2011
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Service public

    Informations forums :
    Inscription : Décembre 2011
    Messages : 54
    Points : 67
    Points
    67
    Par défaut
    Comme tu le dis, la conversion est implicite, je parlais simplement du fait d'expliciter les choses pour une lecture plus directe du code, rien de plus Mais je le répète, ce n'est qu'un avis personnel!

  17. #17
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Ecrire " == false" (ou true) est inutilement verbeux. Mais on est tous d'accord pour dire que ce code est obscure. Personnellement, j'utilise très peu l'opérateur "virgule", sauf cas particulier (plusieurs initialisation ou incrémentation dans une boucle for par exemple)

    Il ne faut pas oublier que ce code date de quelques années quand même

    Finalement, l'idée est proche de ce dont je parle en début d'année Faut-il bannir le for du C++ ?, ça reste un exercice intéressant pour apprendre la lib standard

  18. #18
    Membre émérite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2008
    Messages
    832
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2008
    Messages : 832
    Points : 2 625
    Points
    2 625
    Par défaut
    Citation Envoyé par Kalith Voir le message
    Seulement le dernier élément, soit ".".
    L'intérêt est de tout écrire en "une instruction", ce qui n'apporte rien en terme de performance, mais peut économiser de la place en terme de quantité de code (c'est discutable ici).
    Pourquoi? Parce que le ";\r\n" (pour windows, naturellement) pèse plus lourd dans le code source que ", " ?

    Personnellement, je me pose aussi la question de l'intérêt de cette ligne-ci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    srand( time(0) ),
                generate( comb.begin(), comb.end(), ChoosePeg );
    Dû à une vieille habitude, je lis toujours le code du main avant le reste (et donc, je déclare toujours les classes et structures pour en placer les définitions après l'endroit où elles sont utilisées, mais c'est juste une habitude) et j'ai tellement bloqué sur cette ligne bizarre que je n'ai pas vu la ligne du return

    Je trouve regrettable de faire du code qui économise la place, et encore pire dans une publication dont l'objectif est d'expliquer aux gens. Eventuellement, on à là une excellente explication de comment rendre un code illisible, mais à part ça...

    Je sais que les GotW sont célèbres, et nombre de ces articles de bonne qualité, mais là, je me demande si il est pertinent de ne pas proposer une solution propre et lisible en tant que "NdT" (note du traducteur) parce que si quelqu'un commence C++ et tombe sur ce... hum... truc, je parie qu'il changera immédiatement de langage!
    Ce serait dommage, puisque je pense que le but est d'expliquer la puissance et la lisibilité de la STL... non?

    Notez que c'est peut-être aussi dû au fait que je sois trop idiot pour le comprendre facilement...

    PS: a noter que je ne dénigre absolument pas le travail du traducteur, j'indiquais simplement que je pense qu'il est contre-productif de publier la traduction exacte dans ce cas précis, si on souhaite faire la promotion de C++ et faire oublier une partie de la réputation de complexité dont il souffre, et que cet article justifie parfaitement (non mais, sérieux, l' "opérator,()" pour s'en servir pour séparer des instructions, il faut vraiment avoir l'esprit tordu...)

    PPS: @gbdivers: désolé de ne pas avoir le temps de participer à la rubrique d'où sort ce travail, mon projet personnel est plutôt chrono-phage ...

  19. #19
    Membre éclairé

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

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Points : 764
    Points
    764
    Par défaut
    Citation Envoyé par Freem Voir le message
    Pourquoi? Parce que le ";\r\n" (pour windows, naturellement) pèse plus lourd dans le code source que ", " ?
    On est d'accord, c'est du chipotage (quoi que tu ne comptes pas les caractères nécessaires à l'indentation de la nouvelle ligne )... À mon avis c'est plutôt pour se donner bonne conscience et passer outre la "règle" selon laquelle on doit toujours sauter une ligne après un point virgule, mais rarement après une virgule.

    Sinon je suis d'accord avec toi, mais c'est toujours délicat d'apporter des corrections aussi importantes dans une traduction. La question se pose d'ailleurs aussi avec l'arrivée du C++11, qui pourrait simplifier/résoudre certains problèmes qui sont traités par les GotW ou autres articles.

  20. #20
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Je ne vois pas de réaction à la solution d'HS là où la solution fut initialement donnée: http://groups.google.com/group/comp....a506b0d2dd86a7 (ne pas oublier que les GOTW étaient des "énigmes" posées sur clc++m)

    En revanche, la solution a été corrigée dans MXC++.

    Pour moi trois choix sont possibles dans la mesure où je considère qu'une traduction ne doit en aucun cas altérer le contenu ou le message de ce qui est traduit:
    - ne pas traduire ce GOTW
    - demander à l'auteur la permission de reprendre le code qui se trouve dans MXC++.
    - signaler en note de bas de page que le code est en fait buggué et qu'il faudrait externaliser les tableaux qui se trouvent dans Count pour lever le bug.

    La solution 2 est préférable (et bien sûr), il faudra préciser d'où vient en fait la solution.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

Discussions similaires

  1. Guru Of the Week n° 42 : utilisation de auto_ptr
    Par gbdivers dans le forum C++
    Réponses: 1
    Dernier message: 19/10/2012, 12h19
  2. Guru of the Week 104
    Par gbdivers dans le forum C++
    Réponses: 15
    Dernier message: 25/04/2012, 16h27

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