La programmation en C++ moderne

Apprenez la programmation de zéro jusqu'à l'infini !

a marqué ce sujet comme résolu.

Pour Visual Studio Code, pourquoi pas. C’est light. (Par contre, il est possible d’installer facilement un compilo C++ dans les packages ?) Par contre, Docker ? Je n’ai jamais utilisé pour le C++ mais ça me semble être la grosse artillerie pour débuter.

Et déplacer les tutos que tu vires dans des "Annexes" (+ un disclaimer pour préciser que les tutos sur les IDEs sont souvent moins a jour que les IDEs et qu’il ne faut pas hésiter a demander sur les forums)

+2 -0

En fait, Docker c’est l’environnement, mais le débutant lui n’aura rien de plus à faire que de copier les fichiers de configuration qu’on lui donne, faire « Lancer VS Code dans un conteneur » et hop, Docker c’est fini, on se concentre sur Visual Studio Code et C++. À l’intérieur du conteneur, il a tous les outils qu’il faut, il se promène dans son arborescence avec la ligne de commande, en bref, comme s’il utilisait un vrai Linux.

Bonne idée pour déplacer dans les annexes.

Ça permet de ne présenter qu’un même outil pour tout le monde (donc moins de travail pour nous, puisque pas de répétition sur le débogage, sur la séparation en fichiers, etc), ça permet d’avoir les versions les plus récentes de GCC et Clang (donc pas de disparité de ce côté, tout le monde a les mêmes outils), les outils sont libres, gratuits et présents sur toutes les plateformes majeures. Donc je pense réécrire le tutoriel pour partir dessus.

informaticienzero

Sinon, tu fais comme pour le tuto C : tout en ligne de commande. ^^

+0 -0

Je ne suis pas sur que ce soit un problème pour un cours débutant de ne pas avoir exactement la même version du compilateur. Je trouve que MSVC peut etre utilisé sans problème (installation en 2–3 clics, fonctionnalités supportées suffisantes).

Et pour MinGW, le plus simple est d’installer la version de STL (et ce qui est recommandé sur le forum OC) : https://nuwen.net/mingw.html

Ou installer Qt, qui permet aussi d’installer un IDE et MinGW en 2–3 clics.

Je ne connais pas trop Docker, donc je suis curieux de voir (et tester) vos explications pour l’installer. Mais je trouve en général que ce n’est pas très compliqué d’installer un environnement C++ sur Window. (J’ai l’impression que les problèmes que les gens rencontrent viennent du fait qu’ils suivent un tuto obsolète - que je nommerai pas… - et qu’ils ne lisent pas les tutos à jour qu’on leur donne… et on parie combien que cela risque de continuer avec ceux qui vont suivre votre cours ? ;) )

+0 -0

Je suis un peu sceptique concernant l’utilisation de "dev container" avec docker pour des débutants:

  • docker sous windows c’est pas vraiment pratique. Ne parlons même pas du cas où la personne est sur Windows Family, ou pire s’il n’a pas les droits admin. Ce dernier cas est presque systématique en entreprise, pour le gars qui veut juste tester vite fait le tuto et voir s’il part dessus ou pas, ce sera un no go direct à mon avis.

  • docker en soit simplifie beaucoup les choses pour utiliser des containers, mais c’est une technologie très complexe sous le capot, donc pour la majorité des utilisateurs c’est une bonne grosse boite noire. Un débutant se pose souvent 40000 questions sur les outils qu’il utilise, ajouter une couche de boite noire n’arrangera pas les choses, surtout qu’en soit elle n’a rien à voir avec le C++. N’aura t’il pas déjà bien assez à apprendre avec le langage, le compilateur et l’IDE utilisé?

Merci pour vos retours. De toute façon, rien n’est encore acté, ça ne se fera pas avant la sortie de WSL2.

Néanmoins, les arguments que tu cites @Pataques peuvent aussi valoir dans l’autre sens. Si le mec est en entreprise et a le poste sans droit d’admin, il ne pourra pas plus installer Visual Studio ou Qt Creator.

Quant aux boîtes noires, on se repose sur elles tout le temps. Le processus de compilation est pour un débutant une boîte noire. L’IDE aussi. Même quand on voit l’allocation dynamique, c’est une boîte noire qui nous réserve une portion de mémoire, sans qu’on sache ce qui est fait vraiment.

Il y a tellement d’abstractions qu’on ne peut pas tout dévoiler, tout expliquer. Et puis il suffit d’expliquer que Docker permettra d’avoir le même environnement pour tout le monde et cela conviendra pour la plupart des lecteurs. Ceux qui veulent aller plus loin le feront seuls, car de toute façon un cours ne peut pas tout aborder.

Avant de prendre une décision, je vais attendre déjà la sortie de WSL2 et de Docker for Windows utilisant WSL2. Si tout fonctionne comme ils le prévoit, vu qu’on aura un vrai Linux sous le capot, même Windows Familial marchera. :)

Si le mec est en entreprise et a le poste sans droit d’admin, il ne pourra pas plus installer Visual Studio ou Qt Creator.

Alors que vim et cygwin (via mobaxterm, le plus simple aujourd’hui), pas besoin d’être admin :D

Ceci dit, QtCreator s’installe (depuis les sources) sans être admin (sous linux du moins, pour Windows, je ne sais pas)

L’idée d’un docker n’est pas forcément déconnante. Au boulot, c’est des VM (de 20+ gigas) que je distribue. Et justement, la dernière fois ils ont tous utilisé QtCreator (je n’impose rien), et j’ai été bluffé par la dernière version qui comprend LSP visiblement. J’ai trouvé que c’était pas mal car ça permet de les aider à corriger les erreurs avant même de lancer la compilation. J’ai trouvé le processus moins psychologiquement violent.

Une petite relecture, en espérant ne pas radoter.

§ OO/ penser en termes de services

avec tel algorithme appliqué à tel structure ou tel type

"structure" est féminin -> telle


§ un chouilla plus loin: le pressing

Dans ce cas, toute la complexité de tri par couleur, de bonne quantité de lessive et autres est cachée

"cachée" a tendance à être un faux ami côté conception. Je préférerai presque "déléguée". Mais cela a aussi un sens fort :(. Quid "confiée à un spécialiste" ?

Autre reformulation qui me vient à la volée: "On n’a pas besoin de maîtriser les arcanes du nettoyage, des gens/spécialistes en qui on peut avoir confiance vont en assumer la responsabilité."

A ce propos, le terme a été employé mais pas posé: tout cela n’est jamais que de l’abstraction, et c’est une pierre fondamentale (je ne sais plus parler français) de la conception OO.


§ OO/exemple concret

j’ai fais remarquer

-> effe-a-i-té, pas esse ;)

Mais… ce n’est pas une écriture à 4 mains?


§ OO/un peu de vocabulaire

Un objet n’est ni plus ni moins qu’une valeur qu’on manipule

une donnée, plutôt qu’une valeur, non?


§ OO/le type

Justement, comment sont définis les services qu’un objet peut rendre ?

Ne faudrait-il pas préciser que c’est le cas du C++ et d’autres langages à typage statique (?) ? Et que ce n’est pas vrai dans certains, plus proches de la définition OO originelle, où à la place on demande à un objet de répondre à un message, et que peut-être on ne sait pas s’il en est capable avant d’essayer.

on pourra créer autant d’objet

accorder au pluriel "objets"


§ OO/donc en C++

définir des fonctions à l’intérieure d’une structure

pas de "e" final à "intérieur"


§ OO/quelle méthode doit-on employer

Le prototype n’a rien d’extraordinaire, mais l’implémentation

Hum… j’aurai plutôt parlé de "déclaration", et de "définition". Je n’ai pas la norme sous les yeux pour voir quels sont les termes officiels.

la fonction à laquelle il a affaire

-> "à faire", IIRC


§ OO/séparons tout ça

séparer notre code entre définition et implémentation

Tu veux dire "définition de la classe" et "définition des fonctions" :)

vous-mêmes

Pas sûr qu’il faille un 's’ à "même" ici

découpez et vous gagnerez en lisibilité .

Avec le folding supporté par tous les outils modernes, est-ce que cela est toujours vrai? L’intérêt est lié à la chaine de compilation&link, et éventuellement à des considérations de distribution de code source.


§OO/invariant

Imaginez notre blanchisserie. Son invariant est que votre linge soit toujours en bon état

Je dirai plus qu’il s’agit d’une post-condition.

Pour info, mon exemple d’invariant est le suivant (en plus il se transpose bien à l’héritage et aux membres protégés: "peut-on avoir plus confiance aux enfants qu’aux voisins?"):

Mon chat est un drogué: il se fait des lignes de savon de Marseille. Je suis donc obligé de laisser la porte de la buanderie fermée en permanence.

Le voisin a un pb avec sa machine et vient toquer à la porte pour laver son linge. Pas de soucis, je lui file un double des clés et lui fais part de mon invariant/TOC: la porte de la buanderie doit toujours restée fermée.

Premier jour, il vient, et lave ses couleurs, il pense à bien refermer la porte à chaque fois. Nickel!

Deuxième jour, il revient pour son linge foncé. En court de route, appel de l’école: il y a une urgence et doit filer récupérer son gamin. Situation totalement exceptionnelle qui le fait partir précipitamment sans penser à refermer la porte de la buanderie.

Mauvaise surprise au retour, le chat est intoxiqué et je dois aller au véto.

-> discussions sur la confiance, les invariants, pourquoi on protège, etc.


même §

cours-jus

-> court-jus


§ privé VS public

inutile de le laisser masquer

-> laissé

Après: je dirai que par soucis d’homogénéité, c’est mieux d’éviter de trop mélanger les attributs publics et privés dans une même classe. -> principe de la moindre surprise.


§ Qui va construire

De même, l’initialisation ne se fait pas dans le corps du constructeur

Je rajouterai bien un "exclusivement". Car on peut le faire, mais ce n’est pas toujours le mieux, etc., etc.


même §

J’aurai bien appelé la fonction de réduction dans le constructeur. Ce n’est n’est alors qu’un renforcement technique de l’invariant.


§ 1 ctr, des ctrs

une seul ligne

-> seule*


std::string const d { iterateur, fin };

Je n’aime pas l’unicorn syntax pour les types conteneurs. Je préfère la réserver aux séquences de valeurs à stocker.


§ mutable

Une fonction membre constante, c’est une fonction qui ne modifie pas l’objet auquel elle appartient.

-> une fonction qui promet. Ce n’est pas parce que l’on ne modifie pas (chose que le compilateur sait observer), que nous (développeurs) le faisons promettre dans le code.

dans le cas de std::vector, la fonction membre front

Je préférerai parler dans un premier temps de size ou de empty car il n’existe pas de surcharge non-const, et que quelqu’un de curieux pourrait voir qu’il y a plusieurs versions de front.


Je relirai attentivement la page sur la sémantique de valeur plus tard

Sémantique de Valeur

Intro

J’aime bien l’exemple du compte en banque. J’imagine qu’il est réutilisé plus tard pour dire que des comptes peuvent êtres différents mais disposer de la même somme.

ordre

On peut aussi définir

-> "on peut aussi parfois définir": car toutes les valeurs ne sont pas ordonnables, et on pourrait mal généraliser la phrase.

§ Copier

On peut créer autant d’instances du même objet

La phrase est bizarre si on prend le vocabulaire précédent qu’une instance (d’une classe) est un objet. Dans l’immédiat, je n’ai pas de bonne tournures: "autant de duplicatas d’un même objet"?

autre instance de l’objet

-> une autre instance de la classe

affectation

affecter une copie d’un autre objet à notre instance après coup

J’aurai plutôt dit:

-> affecter une nouvelle valeur à notre instance en dupliquant (/par duplication de?) celle d’un autre objet

Chainage des affectations

Peut-être préciser: "mais pourquoi veut-on faire ça?" que c’est pour garder une compatibilité/similitude de comportement avec le C, et suivre le principe de la moindre surprise. C’est facile et rapide à faire, donc on le fait systématiquement.

Des curieux pourraient se demander pourquoi un retour par référence. Je ne suis pas sûr qu’il faille montrer les horreurs que cela permettait et que l’on garde pour rester 100% compatibles toujours. Parler d’optim peut-être seulement? Et encore…

[nv]ous-mêmes

-> pas de "s" à "même": les explications ici: http://www.lefigaro.fr/langue-francaise/expressions-francaises/2017/09/24/37003–20170924ARTFIG00002-nous-memes-ne-faites-plus-la-faute.php

Je soupçonne que c’est un peu partout dans le cours.

"Les opérateurs d’affectation intégrés"

C’est pas "composés" qu’on dit? (pour coumnpound)

Opérateur +

Puisque le paramètre a est une copie

C’est plus subtil. Beaucoup plus subtil. Mais vous le savez déjà.

Amitié

Ici elle n’est pas nécessaire pour op+. Mais elle a un avantage très avancé (en terme de prérequis pédagogiques) relativement à la résolution de noms.

Libre, membre

J’ai peur qu’il faille creuser la question. En TP (sur la matrice), je vois systématiquement des problèmes avec des gens qui vont définir T op+(T, T) dans la définition de la classe. Il y a souvent deux soucis: le premier est qu’ils ne savent jamais où placer la définition même si deux planches avant je montre comment faire. Le second (bien moins important) est qu’ils n’aiment pas les références constantes.

Du coup je me retrouve à chaque fois à expliquer :

  • que T1::op¤(T2) <~> op¤(T1&, T2),
  • car quand le compilateur voit a ¤ b, il cherche dans l’ordre type(a)::op¤(type(b)), puis op¤(type(a), type(b))
  • et que T1::op¤(T2, T3) <~> op¤(T1&, T2, T3) et qu’il n’y a pas d’opérateur ternaire surchargeable et qu’en particulier + ne l’est pas (ternaire).
  • et que c’est comme ça par choix syntaxique

Et même avec ça, je sens que je galère à bien faire comprendre à chaque fois. Du coup, je suis intéressé par tout RETEX d’enseignement cours/TP sur ces sujets.

Je sens qu’il y a une subtilité pour que ça passe bien et sans accrocs, et que je ne l’ai pas encore.

objets fonction

ce § peut être sorti de la sémantique de valeur je pense.

Salut à tous,

Ces derniers temps, l’écriture a ralenti, mais on compte bien reprendre. Au programme, les deux premiers chapitres de la partie POO sont presque terminés. Notez l’apparition d’une nouvelle section dans le premier chapitre, qui parlera notamment du S de SOLID, ainsi que de la loi de Déméter.

De son côté, @mehdidou99 avance petit à petit sur l’étude de cas.

Je pense qu’on enverra la partie POO quand les quatres premiers chapitres seront terminés, ce qui permettra de disposer déjà de la sémantique de valeur. On verra, en fonction de l’avancement, si on publie l’étude de cas en même temps ou après.


Bonjour les agrumes !

La bêta a été mise à jour et décante sa pulpe à l’adresse suivante :

Merci d’avance pour vos commentaires.

Salut à tous,

Voilà donc la partie sur S, O et Déméter écrite. Je vais pouvoir attaquer le chapitre 3 et la sémantique de mouvement. N’hésitez pas à nous faire des retours, car c’est grâce à vous que ce cours peut devenir meilleur encore. :)

PS : @lmghs je ne t’ai pas oublié, j’ai pris en compte plusieurs de tes remarques. Désolé de ne pas avoir fait de diff par contre.


Bonjour les agrumes !

La bêta a été mise à jour et décante sa pulpe à l’adresse suivante :

Merci d’avance pour vos commentaires.

Partie sur les invariants.

Rappelons que cette opération est mathématiquement impossible.

Elle n’est pas définie en mathématiques classiques, c’est un peu différent. Et pour le cas d’un langage de programmation, c’est à la charge du langage de dire ce que l’on fait, en l’occurrence pour C++, c’est pareil: c’est pas défini.

(Les différents exemples d’invariants)

J’ajouterais bien un: "L’invariant de vector c’est que sa taille est toujours inférieure ou égale à sa capacité et que les accès à toutes les cellules entre 0 et sa taille sont des cellules valides", pour se relier à quelque chose de programmatiquement très tangible.

En fait, dès qu’il y a des conditions à respecter quand on veut créer un objet, c’est qu’il y a un ou plusieurs invariants.

Le un ou plusieurs n’est pas forcément nécessaire. Si tu as "des invariants" c’est "un invariant" qui est la conjonction de tous.

C’est parce qu’en C++, différentes visibilités sont possibles pour nos attributs et services. […]

Autant je pense qu’effectivement, expliquer protected n’est pas nécessaire maintenant, autant je ne pense pas qu’il soit nuisible de dire "il y en a trois, protected on en parlera plus tard, promis". Je ne pense pas que ça perdrai le lecteur.

Au contraire, dans le cas où un attribut existe mais n’intervient pas dans l’invariant de la classe, inutile de le laisser masqué, autant le rendre public. Toujours dans notre exemple, on pourrait définir le nombre de messages à envoyer. Nos services exposés ne dépendent pas de ce paramètre, il n’intervient donc pas dans l’invariant et il n’y a aucun danger à le laisser public.

D’un autre côté d’un point de vue conception, ça sentirait un peu le pâté. L’idéal reste quand même qu’une classe expose seulement ce qui est utile à son fonctionnement. Exemple ici, si manifestement la variable n’a pas d’impact sur le fonctionnement des services, qu’est ce qu’elle fait là ?

De même, l’initialisation ne se fait pas dans le corps du constructeur mais directement en-dessous de sa signature. Ce sont deux particularités des constructeurs.

Le problème de cette affirmation c’est que pour un débutant, je pense que ce qui vient ensuite peut clairement avoir l’air de la contredire (avec le constructeur qui reçoit une string). Donc soit amha, il faut tout de suite bien spécifier la différence entre la liste d’initialisation et le bloc du constructeur. Par exemple avec un petit exemple intermédiaire qui traduirait l’initialisation directe des champs dans le bloc en terme de liste d’initialisation + affectation.

(Pour la fourberie: le constructeur de string pourrait être une fonction non membre :P ).

Par exemple, dans le cas de std::vector, la fonction membre front est un simple accès en lecture au premier élément du tableau.

Pas extra comme exemple, il y a deux versions : une const et une qui ne l’est pas. Prend plutôt size ou capacity.

A la fin de cet exemple, je pense que ce serait pas mal d’aller un poil plus loin en renforçant l’invariant de la fraction de façon à ce qu’elle soit toujours irréductible.

Partie sur SOLID

L’exemple de vector pour l’OCP n’est pas fou. La capacité à étendre une classe tel que défini par Martin est étroitement liée au mot clé "extends" en Java, et donc à l’héritage. Un autre schéma commun est lié aux interfaces où dans un cas comme:

class Interface {
  // functions
};
class X : public Interface {

};

On peut aussi étendre X par quelque chose comme:

class Y : public Interface {

private:
  X internal ;
};

Par ailleurs, la paramétricité de vector n’est pas une extension, c’est de la paramétricité, on étend pas les comportements de la classe en question, on se contente de l’instancier pour un type particulier. Peu importe le type que tu lui donnes en entrée, le comportement de vector est le même, modulo les traits qui sont de toute façon une nouvelle fois internes à vector (donc tu ne les étends pas non plus).

Bref, mis à part de le "S" de SOLID, tu ne peux pas introduire grand chose à ce stade du tutoriel.

Les classes peuvent posséder des invariants, c’est-à-dire des garanties, des contrats, qui doivent être constamment garantis pour que l’objet soit correct.

Doivent être garantis avant et après chaque appel de fonction membre. Le rôle des fonctions membres non-const étant même précisément d’être capable de violer temporairement l’invariant de l’objet pour le faire changer d’état. (Les fonctions const étant autorisées à violer les invariants si d’un point de vue externe le comportement observable est toujours cohérent).

Tout d’abord, vraiment merci pour ce tutoriel magnifique. J’avais commence par apprendre sur OC. Vous savez a quel point ce tutoriel est critique… Bref, je ne comprend pas toujours certaines remarque qui sont faites a l’encontre de ce cour. D’ailleurs plein de suggestion apparaissent ici dans les commentaires pour ameliorer certaines choses. Mais je n’en comprend pas l’impact non plus. Je pense qu’une partie des choses que je ne comprends pas ne peut et ne se resoudra qu’avec le temps et la pratique (beaucoup de pratique comme suggere dans le tuto d’ailleurs). Meme si c’est assez frustrant, je n’est pas les capacites intellectuelles et/ou le recul necessaire maintenant pour comprendre un certain nombre de choses. Tant pis.

Concernant Mes remarques, etant assez lent dans mon avancement (sur le tutoriel) et dans ma comprehension (c’est parfois maximum 10 pages par jour quand le sujet me semble difficile. Parfois c’est pire) , j’ai pas beaucoup de chose a dire. J’ai vu des trucs qui m’ont interpele. Je ne peux pas en parler soit parce que je ne m’en rappel pas tout de suite, soit parce que me connaissant, je prefere relire a tete reposee histoire d’etre sur que le probleme ne vient pas de moi. La seule chose que j’aimerais signaler c’est au niveau de l’ecriture de certains template. Je crois ca a avoir avec l’evolution des compilateurs qui avec les nouveaux standard et les expressions constexpr vont maintenant pouvoir generer du code adapter au contexte.

Notez qu’on doit préciser, entre chevrons <>

 std::cout << std::greater<int>{}(2, 3) << std::endl;

Si j’ecris ca…

std::greater {} ( 2, 3 );

Ca marche aussi (du moment que -std=c++17). C’est plus a jour et c’est plus simple a ecrire je crois.

Une derniere chose. Concernant les predicats.

Un prédicat est une expression qui prend, ou non, des arguments et renvoie un booléen. Le résultat sera donc true ou false, si la condition est vérifiée ou non.

Dans le fichier d’en-tête <numeric> , il existe une fonction répondant au doux nom de std::accumulate , qui permet de faire la somme d’un ensemble de valeurs, à partir d’une valeur de départ. Ça, c’est l’opération par défaut, mais on peut très bien lui donner un autre prédicat, comme std::multiplies , afin de calculer le produit des éléments d’un ensemble.

Je sais pas. Mais je crois que l’operation "()" de std::multiplies renvoie un objet de type compatible avec la multiplication de ses parametres. Est ce qu’un c’est un predicat du coup? Et puis c’est pareil. Tu fais…

auto produit { std::accumulate(std::cbegin(nombres), std::cend(nombres), 1, std::multiplies<int> {}) };

mais on peut aussi faire

auto produit { std::accumulate(std::cbegin(nombres), std::cend(nombres), 1, std::multiplies {}) };

et comme je disais ca s’inscrit dans cette nouvelle vision c++; donc moins de template et plus de metaprogrammation.

+1 -0

Un message sur OC pour une correction sur std::string : https://openclassrooms.com/forum/sujet/c-modernes-chaines-de-caractere-avec-type-auto#message-93464270

  • ajout du using
  • ajout du const ?
  • remplacer par un code qui ne fonctionne qu’avec std::string et pas char*

D’ailleurs plein de suggestion apparaissent ici dans les commentaires pour ameliorer certaines choses. Mais je n’en comprend pas l’impact non plus.

mougnolribama

Deja, le premier impact, c’est que les corrections proposées ici sont appliquées sur ce tutoriel, contrairement au tutoriel de OC. On déjà fait plusieurs review du tuto d’OC mais les corrections n’ont jamais été faites après plusieurs années.

Rien que cela, ca a un très gros impact sur la qualité.

Meme si c’est assez frustrant, je n’est pas les capacites intellectuelles et/ou le recul necessaire maintenant pour comprendre un certain nombre de choses. Tant pis.

mougnolribama

Ce n’est pas une question d’intelligence. C’est juste comme ça qu’on apprend. Prend un enfant de 4 ans et donne lui un cours d’architecture des ordis. Il n’arrivera probablement pas a allumer un ordi après avoir suivi ton cours. Mets le devant un ordi et montre lui de bouton de démarrage, il arrivera a allumer un ordi ensuite.

Il faut commencer par manipuler quelque chose avant de comprendre comme cela fonctionne. Un simple hello world en C++ utilise en interne des techniques assez avancées. Est-ce que tu sais comment fonctionne std::cout en détail ? Probablement pas. Et pourtant, tu as surement compris comment faire un hello world.

S’il y a des points qui te bloque vraiment, il ne faut pas hésiter a en parler aux auteurs. Parfois, il est possible de rendre plus compréhensible juste en modifiant la tournure d’une phrase ou en ajoutant une info.

Mais il faut surtout oublier cette histoire d’intelligence et il faut se faire confiance.

La seule chose que j’aimerais signaler c’est au niveau de l’ecriture de certains template. Je crois ca a avoir avec l’evolution des compilateurs qui avec les nouveaux standard et les expressions constexpr vont maintenant pouvoir generer du code adapter au contexte.

Notez qu’on doit préciser, entre chevrons <>

 std::cout << std::greater<int>{}(2, 3) << std::endl;

Si j’ecris ca…

std::greater {} ( 2, 3 );

Ca marche aussi (du moment que -std=c++17). C’est plus a jour et c’est plus simple a ecrire je crois.

Oui, c’est ce qu’on appelle le Class template argument deduction (CTAD) https://en.cppreference.com/w/cpp/language/class_template_argument_deduction

(Par contre, constexpr n’a rien a voir avec les templates ou le CTAD)

Une derniere chose. Concernant les predicats.

Un prédicat est une expression qui prend, ou non, des arguments et renvoie un booléen. Le résultat sera donc true ou false, si la condition est vérifiée ou non.

Dans le fichier d’en-tête <numeric> , il existe une fonction répondant au doux nom de std::accumulate , qui permet de faire la somme d’un ensemble de valeurs, à partir d’une valeur de départ. Ça, c’est l’opération par défaut, mais on peut très bien lui donner un autre prédicat, comme std::multiplies , afin de calculer le produit des éléments d’un ensemble.

Je sais pas. Mais je crois que l’operation "()" de std::multiplies renvoie un objet de type compatible avec la multiplication de ses parametres. Est ce qu’un c’est un predicat du coup?

mougnolribama

Tu as tout a fait raison. Ce n’est pas un prédicat. C’est a corriger.

D’ailleurs, c’est explicite dans la doc. Par exemple std::find_if https://en.cppreference.com/w/cpp/algorithm/find il est écrit "UnaryPredicate". Alors que pour https://en.cppreference.com/w/cpp/algorithm/accumulate, c’est écrit "BinaryOperation".

La définition de "Predicate" en C++ est donnée dans la doc : https://en.cppreference.com/w/cpp/named_req/Predicate

et comme je disais ca s’inscrit dans cette nouvelle vision c++; donc moins de template et plus de metaprogrammation.

mougnolribama

meta prog = template en C++. Tu voulais probablement dire "donc moins de template et plus de programmation générique".

+2 -0

Deja, le premier impact, c’est que les corrections proposées ici sont appliquées sur ce tutoriel, contrairement au tutoriel de OC. On déjà fait plusieurs review du tuto d’OC mais les corrections n’ont jamais été faites après plusieurs années.

Rien que cela, ca a un très gros impact sur la qualité.

Cet impact la je l’avais plus ou moins compris. Je parlais de comprendre les avantages ou les inconvenients de certains usages. Parfois pour moi c’est la meme chose et les commentaires sur la bonne facon d’ecrire un programme sont souvent un peu obscurs.

Je penses, gbdivers, que tu apportes une tres bonne explication a ce sujet:

Il faut commencer par manipuler quelque chose avant de comprendre comme cela fonctionne. Un simple hello world en C++ utilise en interne des techniques assez avancées. Est-ce que tu sais comment fonctionne std::cout en détail ? Probablement pas. Et pourtant, tu as surement compris comment faire un hello world.

Concernant la confiance…

Mais il faut surtout oublier cette histoire d’intelligence et il faut se faire confiance.

S’il y a des points qui te bloque vraiment, il ne faut pas hésiter a en parler aux auteurs. Parfois, il est possible de rendre plus compréhensible juste en modifiant la tournure d’une phrase ou en ajoutant une info.

C’est plus un probleme de rythme. J’ai plus souvent l’impression que je fais 10 fois plus d’effort que certains pour y ariver que je ne vais jamais y arriver. Mais tes conseils sur le sujets, je me les repassent en boucle histoire que ca rentre et que je devienne le genre d’informaticien que j’ai envie d’etre ( tres tres bon).

Oui, c’est ce qu’on appelle le Class template argument deduction (CTAD) https://en.cppreference.com/w/cpp/language/class_template_argument_deduction

(Par contre, constexpr n’a rien a voir avec les templates ou le CTAD)

MERCI! Je vois la et dans la suite du post une illustration interressante a mon sens (vue qu’on sort du cadre du tuto: on est un peu dans le vrai monde ) de comment s’appuyer sur la norme pour ecrire du code ou le lire et le comprendre.

Une autre question. C’est a propos de la documentation. j’aime souvent lire les liens en "fr". Je me demandais si c’etait equivalent en "en"?

Plein d’autre merci pour les pistes sur lesquels vous me lancez ( difference entre metaprogrammation et programmation generique, CTAD et qui m’ont fait decouvrir template argument deduction …). Je vais faire un peu de recherche et je reviendrais vers vous avec des reponses mieux structurees qu’elles ne le sont maintenant dans mon esprit.

Encore merci!!!

+0 -0

Bonsoir,

Ca y est, je viens de comprendre comment il fallait faire pour lire la Béta! (et oui tout le monde ne va pas à la même vitesse!) Et j’ai compris aussi comment faire des remarques (C’est pas que je suis un grand expert, mais si ça peut servir …).

J’attendais avec impatience la chapitre sur la POO … je viens de me lancé … je me permets des remarques d’un type de vos futur lecteur: le type de ceux qui n’y connaisse pas grand chose!

Je n’ai pas la prétention que ce soit très utile, mais "c’est vous qui voyez !"

Remarque sur le chapitre Premiers pas avec la P.O.O

1) Le titre :

Je pense que beaucoup de (jeunes) lecteurs (lycéens, universitaires) sont attirées par les titres et par des textes qui gardent un peu d’humour. « Premier pas avec la P.O.O », je suis pas sûr que ce soit très accrocheur ! Pour ma part, j’avais bien aimer le « On passe la seconde », c’est pas possible de trouvez quelque chose dans le même style ? De même pour les introductions de chaque chapitre/page … Je pense que c’est une force du mooc d’OC. J’ai pas beaucoup d’idée, mais « Tout ce que vous avez toujours voulu savoir sur le POO (sans jamais oser le demander) », (C’est peut-être nul, je vous laisse trouver mieux!). Pour l’intro, vous pourriez dire : « La programmation orientée objet, La programmation orientée objet, tous le monde en parle, mais quésaquo ? Déjà chacun a sa définition et son utilisation : chaque langage informatique, chaque expert, chaque contrainte, … Une chose est sûre, c’est très répandu, très utilisé … et, trop souvent, bien mal enseigné. »

(Là aussi, c’est peut-être nul, Je vous laisse trouvez mieux)

Enfin, c’est une idée, je ne sais pas ce quelle vaut. Quand pensez-vous ?

2) Détail de vocabulaire/clarification :

Dans le chapitre :https://zestedesavoir.com/contenus/beta/822/la-programmation-en-c-moderne/la-programmation-orientee-objet/la-p-o-o-quest-ce-que-cest/#quelle-m%C3%A9thode-doit-on-employer, le texte du titre du chapitre est « Quelle méthode doit-on employer » et la première phrase est « Pour créer une fonction membre, il suffit … ». Bien sûr, fonction membre et méthode c’est kif-kif bourricot, mais pour quelqu’un, comme moi qui n’y connaît rien ! (peut pas mettre le même mot ? Ou alors, ajoutez un phrase [humoristique] à la fin de la section juste au dessus « Point de vocabulaire » : « D’ailleurs, pour vous perdre, on mélange les deux dans les chapitre qui suit ! Et oui, il faut que vous vous y fassiez ! »)

3) Erreur dans l’exercice.

Dans l’exercice du chapitre https://zestedesavoir.com/contenus/beta/822/la-programmation-en-c-moderne/la-programmation-orientee-objet/la-p-o-o-quest-ce-que-cest/#un-l%C3%A9ger-probl%C3%A8me, vous modifier le Dénominateur à zero, mais vous n’avez pas modifier le code de main () :

    // Erreur !
    f1.denominateur = 0;
    // Ça va faire boom !
    std::cout << "4/**0 à la place de 2** = " << f1.valeur_reelle() << std::endl;

    return 0;
}

4) Proposition d’amélioration de l’exercice,

en bas du chapitre https://zestedesavoir.com/contenus/beta/822/la-programmation-en-c-moderne/la-programmation-orientee-objet/la-p-o-o-quest-ce-que-cest/#qui-cest-qui-va-construire-%C3%A7a

Je note que vous avez ajouter un « assert » dans votre code exemple, mais que vous n’avez pas ajouté de «#include <cassert> » au début du fichier, … ça ne compile pas.

Bien cordialement.

+2 -0

@Dedeun

Pour le 1), c’est une question assez complexe. Cela va dépendre du public visé, c’est assez difficile de trouver le bon ton. Mais :

  • OC change de nom, ce n’est pas pour rien. Et ils mettent pas mal en avant le professionnalisme de leurs formations (ingénieure en pédagogie).
  • il ne faut pas confondre attractivité et jouer au bon copain.

Prendre un ton très léger, ça va plaire a certaines personnes et pas d’autres. Le gros probleme de OC, a mon sens, est que cela intéresse beaucoup (trop ?) des personnes qui recherchent un apprentissage superficiel et rapide. Ce qui n’est pas le but de ce tutoriel, a priori. Prendre un ton qui ne correspond pas a l’objectif serait une erreur. (Mais c’est aux auteurs de voir le ton qu’ils veulent prendre)

@mougnolribama

Cet impact la je l’avais plus ou moins compris. Je parlais de comprendre les avantages ou les inconvenients de certains usages. Parfois pour moi c’est la meme chose et les commentaires sur la bonne facon d’ecrire un programme sont souvent un peu obscurs.

Certaines recommandations viennent de l’expérience de centaines d’experts qui ont discutés pendant des années, sur des milliers de projets et des millions de lignes de code. Pour cela qu’il est difficile de tout justifier. Meme pour nous, qui sommes devs expérimentés, on ne connait pas forcement en détail tous les arguments (ou on n’est pas tous d’accord).

Donc il faut accepter (pour nous aussi) de respecter les "bonnes pratiques" de programmation, meme si on ne connait pas les justifications. En C++, une référence est les C++ Core Guidelines (https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines)

C’est plus un probleme de rythme. J’ai plus souvent l’impression que je fais 10 fois plus d’effort que certains pour y ariver que je ne vais jamais y arriver. Mais tes conseils sur le sujets, je me les repassent en boucle histoire que ca rentre et que je devienne le genre d’informaticien que j’ai envie d’etre ( tres tres bon).

Pareil que la confiance, il ne faut pas trop se formaliser la dessus.

Il n’y a pas qu’un seul type de "bon" développeur. Tu mets plus de temps, mais est-ce que tu ne vas pas avoir une meilleure compréhension qu’eux ? Est-ce que tu ne vas pas mieux retenir les informations sur le long terme ? Est-ce que tu ne vas pas être plus imaginatif pour trouver des solutions ? Est-ce que le code que tu produis ne va pas être plus stable et maintenable sur le long terme ?

C’est une tendance qu’on voit de plus en plus de les façons d’apprendre et de pratiquer d’aller au plus rapide, de produire du code le plus vite possible, comme si le nombre de lignes de code écrit a la minute avait une importance. C’est une chose qu’on voit pas mal dans certaines formations et dans les sites d’exos en ligne, mais, pour moi, cela destine plus a former des "pisseurs de code" que des devs. (Pour être concret, au boulot, la plus part des jours, je commit une dizaine ou une centaine de ligne de code sur la journée. Donc très peu. Je passe plus de temps a réfléchir a mon code qu’a l’écrire.)

Une autre question. C’est a propos de la documentation. j’aime souvent lire les liens en "fr". Je me demandais si c’etait equivalent en "en"?

Si tu parles de cppreference.com, il ne faut pas utiliser la version fr. cpprefrence.com très très bien maintenu a jour sur la version en, donc c’est une bonne référence. Mais les versions non en ont été généré automatiquement lors de la création du site et devaient être maintenues par les communautés. Mais ce n’est pas le cas. Donc c’est pas a jour. Si tu veux vraiment lire en français, il est préférable de prendre la version en et faire une traduction automatique de la version a jour dans google translate.

+2 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte