Les commentaires
-
[^] # Re: Nouveau langage
Posté par djano . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 1.
Je commence à détecter un certain trait chez les développeurs C++: l'optimisite proactive aiguë!
-
[^] # Re: Nouveau langage
Posté par Oliver (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 1.
Oui, tu as raison, une bonne façon de faire est de créer un Adaptateur. Mais le sujet de mon commentaire était de surligner l'intérêt des fonctions libres qui permettent d'étendre un objet de l'extérieur. Donc, j'avais volontairement omis les autres possibilités qui nécessitent plus de code, plus de relecture, plus de test, plus de maintenance... ;-) (bon oui, je l'accorde pas tellement plus)
Commentaire sous licence Creative Commons Zero CC0 1.0 Universal (Public Domain Dedication)
-
[^] # Re: Nouveau langage
Posté par djano . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 2.
Oui en gros, c'est la différence entre typage nominal et typage structurel. Chacun a ses avantages et inconvénients. Le typage nominal peut offrir un niveau de sûreté de type très élevé, mais ça se fait au prix de la flexibilité. Le typage structurel est quand a lui extrêmement flexible et il passe partout.
-
[^] # Re: Nouveau langage
Posté par djano . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 2.
Concernant sort, là tu bloques sur l'écriture OO mainstream on dirait. Parenthèse OO: Personnellement, je constate ici l'échec de Java qui comme le C++ a des types primitifs, mais qui a introduit un Top Type (type dont tout objet dérive). Résultat le code de divers algorithmes comme sort est dupliqué entre les tableaux primitifs et les collections à accès direct.
Justement, la version 10 de Java pourrait introduire les value types et ainsi émuler les templates C++ avec diverses spécialisations de code générique (comme les templates C++)
Par exemple, on pourrait enfin écrire
ArrayList<int>et il aurait un vrai tableau d'intderrière ça. À comparer avecArrayList<Integer>qui est un tableau d'objets avec tous plein d'indirections en mémoire.Bon il faudrait déjà que Java 9 finisse par sortir. :-|
-
[^] # Re: Nouveau langage
Posté par djano . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 2.
Comment faire pour passer la structure (classe) à la fonction calcule ?
Tu as oublié une autre solution: tu crée un adaptateur, ce qui grosso modo revient à implémenter des fonctions non-libres
recupere_x()etrecupere_y()(c'est pas bien plus compliqué qu'implémenter des fonctions libres).C'est la création de la classe adaptateur qui vous gêne?
-
[^] # Re: Nouveau langage
Posté par lmg HS (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 3. Dernière modification le 08 décembre 2016 à 15:35.
C'est Alexandrescu, je crois, qui avait pondu un Iterators must go. C'était un des premiers articles de qualité pour pousser vers les remplacement des paires d'itérateurs par des plages (ranges en VO). Entre temps, il est parti vers le D, et je me demande si justement il n'avait pas participé aux ranges en D.
Bref, la STL v2 est dans cette mouvance. Et sur ce point, nous sommes d'accord, les algos de la STL v1 ne sont pas des plus ergonomiques. Ils ont de la souplesse, mais ils l'exigent de nous également.
C++20 le prochain je pense sinon. Et effectivement, il semblerait plutôt que l'on lorgne du côté des pipe UNIX. Sauf que ... au lieu de se contenter d'une monde purement fonctionnel (de variables non modifiables), on traine le boulet OO des états qui sont altérés. D'où le
|=. Dans les autres contraintes, il y a les générateurs à la Python.range::ints()etiota()peuvent ainsi générer un nombre (pseudo) infini d'entiers qui seront générés à la volée. -
[^] # Re: Nouveau langage
Posté par kantien . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 5.
Je suis loin, mais alors très loin d'être un fin connaisseurs des langages de programmations existants, alors je me place surtout au niveau de l'approche paradigmatique.
Par exemple, en OCaml, il y a bien des objets mais la documentation officielle précise explicitement :
This chapter gives an overview of the object-oriented features of OCaml. Note that the relation between object, class and type in OCaml is very different from that in mainstream object-oriented languages like Java or C++, so that you should not assume that similar keywords mean the same thing.
et ils sont de fait utilisés en conjonction avec les modules et foncteurs (qui sont ce qui se rapprochent des
templatedu C++ dans ce langage), comme l'illustre le chapitre 5 sur les exemples avancés avec les classes et les modules. Ce qui rejoint ce que tu disais sur la complémentarité de l'OO et des templates en C++.De même, en Haskell, les type classes sont plus à rapprocher des templates que des classes de la POO (voir Demystifying type classes).
Là où pêchent inéluctablement la POO, c'est dans l'accès à certains niveaux d'abstraction, comme dans l'exemple proposé par arnaudus. Comme tu lui as répondu, pour du code métier, pouvoir faire de l'abstraction sur les types n'est pas nécessairement pertinent, en revanche pour la conception de bibliothèques, cela est plus que de la coquetterie.
Enfin, quand je lis ceci dans un des tes commentaires :
NB: l'équivalent template de l'interface, c'est le concept.
je me dis que l'on se rapproche bien plus de ce qu'est un concept, qu'avec les exemples de la POO du genre : un chat est un animal, donc il faut implémenter le concept de chat via une classe qui hérite de la classe animal.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
-
[^] # Re: Nouveau langage
Posté par pulkomandy (site web personnel, Mastodon) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 3.
Je trouve très surprenant en général que y = f(x) puisse modifier x, et les compilos récents n'ont aucun mal à optimiser v = sort(v) correctement. Ceci dit, j'ai peut-être tendance à tenter de retrouver en C++ des concepts qui viennent des langages de plus haut niveau.
Là il faudrait faire de la programmation fonctionnelle, effectivement C++ n'est pas le meilleur choix pour ça.
elle va supporter l'écriture vi |= action::sort | action::unique;
On peut voter quelque part pour le support du Brainfuck dans C++19?
Je suppose qu'ils ont voulu faire un truc qui ressemble aux "pipes" en shell unix?
-
[^] # Re: Nouveau langage
Posté par arnaudus . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 2.
Concernant sort, là tu bloques sur l'écriture OO mainstream on dirait.
Bah non, ma compréhension du problème est que la généricité de la fonction sort() impose l'utilisation d'itérateurs uniquement parce que les containers de la STL n'héritent pas d'une interface commune.
L'écriture qui est sympa c'est sort(v) pourquoi est-ce que cela devrait être v.sort()?
L'intuition est peut-être la chose au monde la moins partagée, mais pour moi les signatures "intuitives" de ces deux fonctions devraient être
std::vector<T> sort(const std::vector<T> &); void vector<t>::sort();Je trouve très surprenant en général que y = f(x) puisse modifier x, et les compilos récents n'ont aucun mal à optimiser v = sort(v) correctement. Ceci dit, j'ai peut-être tendance à tenter de retrouver en C++ des concepts qui viennent des langages de plus haut niveau.
elle va supporter l'écriture vi |= action::sort | action::unique;
On peut voter quelque part pour le support du Brainfuck dans C++19?
-
[^] # Re: Nouveau langage
Posté par lmg HS (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 3.
J'ai tendance à penser que cette limitation n'est pas propre aux différentes implémentations de la POO que tu cites, mais est inhérente au paradigme lui-même : la POO, qui met en avant la notion d'abstraction, c'est de l'abstraction vue par un enfant de quinze ans et à un moment, ça coince.
J'ai aussi tendance à avoir cet avis, mais dans le doute (car je suis loin de connaitre les langage OO qui flirtent de très près avec le monde fonctionnel) j'ai préféré spécifier un contexte.
-
[^] # Re: Nouveau langage
Posté par pulkomandy (site web personnel, Mastodon) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 5.
C'était surtout un accident, au début :) Quelqu'un s'est dit: "hé, mais on peut faire un langage Turing complet avec ça!". Et ensuite y'a eu des gens pour s'en servir...
-
[^] # Re: Nouveau langage
Posté par kantien . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 4.
Je rajouterai aussi pour avoir essayé de jouer à ça dans ma jeunesse que le paradigme OO (tel qu'implémenté en Pascal/Delphi, C++ et Java) est totalement incapable de modéliser correctement les notions de groupes, anneaux et cie quant on commence à vouloir introduire du dispatch multiple dans des fonctions.
J'ai tendance à penser que cette limitation n'est pas propre aux différentes implémentations de la POO que tu cites, mais est inhérente au paradigme lui-même : la POO, qui met en avant la notion d'abstraction, c'est de l'abstraction vue par un enfant de quinze ans et à un moment, ça coince.
Dans un de ses commentaire, Olivier H disait : « Le mot-clé
templatefait peur, démystifions-le ;-) » : je suis impatient de lire une de vos dépêches spécifique à la description, au fonctionnement et à l'usage des templates.Juste une question : j'ai lu que le langage des template était Turing-complet, pourquoi lui avoir conféré cette propriété ? N'est-ce pas plutôt un défaut ?
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
-
[^] # Re: Nouveau langage
Posté par lmg HS (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 5.
Utiliser la SL a tout à voir avec la programmation générique. Avant de disposer d'un
std::vector<>, il faut l'écrire, et après libre à l'utilisateur de s'en servir. Convergeons vers ton exemple (hors STL mais dans la SL) il y astd::basic_string<>ou mêmestd::basic_ostream<>. Très peu ont conscience que ces trucs existent et pourtant ils s'en servent au travers des typedefsstd::string,std::ostream, ou carrément via la variable globalestd::cout.Ces types sont génériques. Si les chaines ne piochent dans le paradigme OO que l'abstraction et l'encapsulation, les flux sont quant à eux plein d'héritage, multiple de surcroit, de points de variations dynamiques (ou comment filtrer à la volée un flux ou l'altérer pour justifier un texte p.ex.), de design pattern Stratégie, et je peux en oublier. Et ? Ils sont totalement génériques sur le type de caractères, et sur les descriptifs des caractères.
Nous sommes du côté d'une bibliothèque et pas d'un code métier. Et c'est probablement ça qui fait toute la différence. Côté métier offrir de la généricité est moins souvent pertinent. De fait une classe
EtatCiviln'a pas grand intérêt à être générique. Côté bibliothèque j'ai pu travailler avec ITK et OTB, là on a des types images dans une hiérarchie avec pourtant un paramètre template pour le type de pixel. On a aussi des hiérarchies encore plus touffues pour dire qu'un truc assimilable à une image peut être une image, un fichier ou une transformation qui va servir à calculer une nouvelle image. Pour le coup ITK utilise des hiérarchies là où la STL (+ std::string) est 100% orientée concepts.Concernant
sort, là tu bloques sur l'écriture OO mainstream on dirait. Parenthèse OO: Personnellement, je constate ici l'échec de Java qui comme le C++ a des types primitifs, mais qui a introduit un Top Type (type dont tout objet dérive). Résultat le code de divers algorithmes commesortest dupliqué entre les tableaux primitifs et les collections à accès direct. Python n'a pas ce problème. Il y a un top type chez lui, mais pas de type primitif.Côté écriture de
sort, la STL v2 est en cours de préparation. Le C++ assume totalement que la généricité est plus adaptée que des hiérarchies compliquées pour des algorithmes. L'écriture qui est sympa c'estsort(v)pourquoi est-ce que cela devrait êtrev.sort()? Avec CLOS, la syntaxe d'appel est(func x y z). Ce qui rend la gestion du dispatch multiple tout ce qu'il y a de plus naturel. Une petite discussion à ce sujet dans un article que j'avais bien aimé (le lien pointe directement sur le paragraphe qui discute s'il faut écrire kick the dog ou dog the kick).Pour en revenir à la STL v2, en plus de l'écriture
action::unique(action::sort(vi));, elle va supporter l'écriturevi |= action::sort | action::unique;qui marcheront aussi sur des tableaux natifs ou sur n'importe quel conteneur à accès direct (seulement? je n'ai pas vérifié) qui exposebegin()etend()en libre ou en membre.Pour la complexité de la STL, je dirai que pour un bonne part c'est une question d'habitude. Pour avoir lu et écouté Stepanov, ce à quoi il a abouti est naturel. Comme en maths, il voit que chaque algo a des prérequis pour être appliqué, à partir de là, hormis les
template <typename NomdeConcept1, ...en début de signature, le reste est franchement clair. Après pour le code des implémentations de la SL, il y a la quasi obligation de tout préfixer avec des tirets-bas et la volonté d'auto-adaptativité à la nature des choses manipulées histoire d'optimiser (nous sommes en C++ après tout), ce qui ne rend pas la lecture toujours triviale. Plus des hacks pour éviter de produire des messages d'erreurs trop inintelligibles, plus de la programmation par contrat. Mais est-ce que cela nous concerne vraiment ?Je rajouterai aussi pour avoir essayé de jouer à ça dans ma jeunesse que le paradigme OO (tel qu'implémenté en Pascal/Delphi, C++ et Java) est totalement incapable de modéliser correctement les notions de groupes, anneaux et cie quant on commence à vouloir introduire du dispatch multiple dans des fonctions.
-
[^] # Re: Nouveau langage
Posté par arnaudus . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 3.
Je veux un tableau dans une classe concrète? std::vector<>. C'est générique et je m'en sers.
J'ai l'impression qu'on ne se comprend pas, et au bout d'un moment ça tourne en rond. Je pense que personne ici ne parle de ne pas utiliser les conteneurs de la STL ; utiliser la STL n'a pas grand chose à voir avec la programmation générique.
La question (telle que je la comprend), c'est de choisir entre
struct EtatCivil { string nom; string prenom; };et
template<typename n, typename p> struct EtatCivil { n nom; p prenom; };comme paradigme de base. Sans aller jusqu'à prétendre qu'il faut 100% de l'un ou de l'autre, mon argument c'est que la plupart des problèmes ont une solution avec l'un ou l'autre, et que comme les deux sont très difficilement fongibles, on va orienter l'ensemble de l'architecture du programme dans un sens.
Je veux trier un tableau ? std::sort()
Je pense que c'est un excellent exemple. C'est générique? OK. Mais l'ergonomie est dégueulasse, parce que tu as oublié que ça s'utilisait comme ça :
std::sort(v.begin(), v.end());. Évidemment, à force de voir ça, on est habitué, mais tu ne trouves pas quev.sort()serait bien plus élégant? Il permettrait aussi le polymorphisme si tous les containers dérivaient d'une interface STL_cont. Bref, la programmation générique pour la bibliothèque standard, c'est un choix technique, mais ça me semble assez excessif de prétendre que c'est pratique et ergonomique ; d'une manière générale, la STL est relativement imbittable, les syntaxes sont contre-intuitives, et le code est assez illisible. -
[^] # Re: Nouveau langage
Posté par groumly . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 3.
Certes, mais en même temps, exposer dans ta sérialisation le nom du membre (côté programme) est vraisemblablement une mauvaise idée
Dans la majorité des cas, non, ca change pas grand chose. C'est pas la meilleure idée de la création, mais c'est pas une hérésie non plus.
Dans les cas qui restent, regarde ce que fait Jackson en Java, avec un système d'annotations qui permet de d'abstraire a 100% du nom des champs, et de leur type. C'est foutremenr efficace, et si j'avais un truc pareil en swift/objc, je virerais direct 10% de mon code. -
[^] # Re: Nouveau langage
Posté par groumly . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 2.
et ça va faire d'excellents exercices pour les gens qui aiment se prendre la tête.
C'est pas la définition d'un programmeur c++ ça?
-
[^] # Re: Nouveau langage
Posté par lmg HS (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 2.
Les projets réels les utilisent tout le temps.
- Je veux un tableau dans une classe concrète?std::vector<>. C'est générique et je m'en sers.
- Je veux un truc qui va collecter automatiquement la mémoire ou n'importe quoi d'autre ?std::unique_ptr<>.
- Je veux trier un tableau ?std::sort()
- Je veux des images avec des types de pixel générique ? Ca marche aussi.On ne va pas faire 100% dans un style et 100% dans un autre. On va prendre le style qui va bien pour un besoin donné. De la même façon que l'on ne va pas dériver pour le plaisir. On compose bien souvent à la place car cela offre plus de souplesse en ouvrant la porte au pattern Stratégie.
PS: Dans le monde des typeurs de canards cela que l'on nomme juste "polymorphisme" désigne le "polymorphisme paramétrique" qui en C++ correspond aux templates, et qui est statique (en C++).
-
[^] # Re: Nouveau langage
Posté par whity . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 3.
Ce n’est pas une question de langage, c’est aussi une question que certaines choses ne sont pas une bonne idée. Un grand classique, c’est le coup de si B dérive de A, alors vector dérive de vector qui est en réalité une très mauvaise idée (violation flagrante du LSP).
La question, c'est plutôt "est-ce que des projets réels vont utiliser ça"?
Ça m’est arrivé. Personnellement, je ne vois pas ça comme des incompatibilités, mais des complémentarités. Après, quand tu commences à voir les bénéfices du polymorphisme statique, tu as tendance à ne vouloir utiliser plus que ça :).
Mes commentaires sont en wtfpl. Une licence sur les commentaires, sérieux ? o_0
-
# dans l'exemple, is_function ne marche pas, il faut utiliser is_member_funciton_pointer
Posté par DerekSagan . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 1.
Dans l'exemple donné avec if_function, en fait ça ne marche pas avec gcc 7 ni le dernier clang, parce que T::f n'est pas une fonction statique.
Voir ici l'erreur de compilation:
https://godbolt.org/g/qIPNxgEn revanche avec is_member_function_pointer on y arrive:
https://godbolt.org/g/NNbYBwIl y a peut-être d'autre façon de corriger, je ne suis pas un gourou méta-programmation.
L'exemple cité dans le corps de la dépêche ne compile que parce que le template n'est pas instancié mais seulement défini.
Voilà, vivement c++17, et merci pour la dépêche instructive.
-
[^] # Re: Nouveau langage
Posté par arnaudus . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 3.
je sais ne pas pouvoir vouloir d'un T ITruc::operator non plus—oui, de connaitre la limitation, ça oriente fortement ce que je m'autorise à vouloir faire.
Oui, donc dans les faits si tu ne veux pas utiliser le polymorphisme, bah la programmation à base de templates ne te pose pas de problème :-) Encore une fois, mon point de vue n'est pas de dire que la programmation générique c'est pourri, c'est de dire que le C++ OO et le C++ générique (au sens de templates non triviaux sur des objets complexes) sont philosophiquement et techniquement incompatibles. On peut concevoir tout un projet en C++ OO ou en C++ générique, mais ça va fortement conditionner le sous-ensemble du C++ et les designs qu'on va utiliser.
Bien sûr, on peut écrire des trucs hybrides, ça va compiler, et ça va faire d'excellents exercices pour les gens qui aiment se prendre la tête. La question, c'est plutôt "est-ce que des projets réels vont utiliser ça"?
-
[^] # Re: Nouveau langage
Posté par lmg HS (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 1.
s/peu réception/peu réceptif—il y a en d'autres, mais là ça ne veut vraiment plus rien dire...
-
[^] # Re: Nouveau langage
Posté par lmg HS (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 3.
OK, je pense voir ce que tu veux dire.
Tu es sur l'interface d'utilisation. J'étais sur POO pour l'interface et templates (qui ne doivent pas fuir au niveau de l'interface) pour l'implémentation—ce qui n'a rien de bancal. Effectivement, le C++ n'offre pas un polymorphisme paramétrique dynamique. En C++, le duck typing c'est 100% à la compilation.
Il y a feintes pour essayer de combiner tout ce beau monde. Cf les articles qui parlent de type erasure en C++—pas sûr que le même sens soit donné dans d'autres communautés.
Bref, il y a des cas de combinaison possibles sur une même famille de types. Et ça marche très bien. Le truc, c'est que dans ce cas, je ne veux pas d'un
at()qui renvoie un template—enfin je ne veux jamais deat()étant peu réception à la programmation défensive, mais c'est une autre histoire, je sais ne pas pouvoir vouloir d'unT ITruc::operator[]()non plus—oui, de connaitre la limitation, ça oriente fortement ce que je m'autorise à vouloir faire.NB: l'équivalent template de l'interface, c'est le concept.
Pour les raisons, je pense qu'il faille aller chercher dans le technique. En C++, les template s'appliquent sur des scalaires comme des objets, et c'est assez contraignant. Je ne sais pas comment font C# et D sur cet aspect.
-
[^] # Re: Nouveau langage
Posté par arnaudus . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 3. Dernière modification le 07 décembre 2016 à 14:45.
PS: Truc peut tout à fait hériter de ITruc ou de TrucImpl. C'est même assez classique quand on veut combiner une variabilité dynamique avec une statique.
C'est super bancal comme solution, parce que ça demande une surcouche, et que l'interface n'est pas templatée. Prenins un exemple trivial : je veux faire un vecteur de vecteurs de différents types. On peut bien créer quelque chose comme
vector<MyVec*>avec desMyvecT<T>qui dérivent d'une classeMyVec, mais à ma connaissance on ne peut pas avoir une méthodeMyVec::at(size_t i) constqui retourne le bon type (*).Si la programmation générique était fongible avec la POO, alors le langage devrait assimiler un template à une interface, et autoriser des choses comme
vector * v;qui se comporteraient comme des pointeurs vers des classes virtuelles pures. Je ne sais pas si c'est pour des raisons techniques ou philosophiques que le C++ a choisi des syntaxes incompatibles, mais je ne vois pas comment on peut l'interpréter autrement que par la volonté de définir deux dialectes qui ne sont pas destinés à cohabiter dans le même code.(
*) Enfin si, je crois qu'on peut si la méthode retourne unvoid*qu'on peut caster avec un typename qu'on aurait défini dansMyvec<T>. Je ne sais pas s'il existe une personne sur terre qui pourrait croire que c'est une bonne idée. -
[^] # Re: Retour arrière sur l'OCP
Posté par Oliver (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 3.
Oui, tu as raison whity, merci. Je corrige :-)
Je résume le commentaire de lmg HS qui en bref disait que nous avons le choix entre :
-
if constexprpour du code simple ; - plusieurs templates pour du code complexe mais ouvert/fermé.
Voici mon commentaire corrigé
if constexprsimplifie le code et tan pis pour le principe ouvert/fermé.
Car souvent, on préfère un code simple plutôt qu'un code complexe mais ouvert/fermé (évolutif).L'idée est d'avoir un code simple, facile à comprendre, et le jour où on a vraiment besoin de le faire évoluer, et bien on le réécrit.
Le risque d'avoir un code complexe mais ouvert/fermé est de garder la complexité et de ne jamais profiter de son principe ouvert/fermé.Je précise, je suis pour le principe ouvert/fermé, et c'est mieux quand on peu allier simplicité à ouvert/fermé.
Je dis juste que des fois (voir souvent) complexifier n'est pas justifié, vaut mieux avoir simple et risquer tout casser.Commentaire sous licence Creative Commons Zero CC0 1.0 Universal (Public Domain Dedication)
-
-
[^] # Re: Nouveau langage
Posté par whity . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 2.
J’ai un peu de mal à te suivre.
Je vais essayer de reformuler ce que j’ai compris. Tu souhaites que :
Foo foo;
foo.baz = "toto";rajoute statiquement un membre baz de type string dans l’instance foo, et uniquement celle-ci ?
Ça casse tout le modèle de compilation C++, et c’est contraire à tout ce à quoi je m’attends quand je lis du C++ (c’est pour ça que je parlais de « casser le langage »). En plus, tu peux très bien obtenir ce résultat en surchargeant l’opérateur [] :
foo["baz"] = "toto";Ce qui certes fait 3 caractères de plus à taper, mais est aussi lisible et beaucoup plus « dans l’esprit » du langage. Quant à l’idée que ce ne serait pas optimal, dans tous les cas, c’est un lookup dans une table de hachage (ou un dictionnaire), je ne suis pas sûr que l’intégrer au compilateur gagnera grand chose.
Mes commentaires sont en wtfpl. Une licence sur les commentaires, sérieux ? o_0
-
[^] # Re: Nouveau langage
Posté par xryl669 . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 1.
Oui, mais c'est lourd à écrire, à lire et donc à maintenir. C'est ça le problème.
-
[^] # Re: Nouveau langage
Posté par xryl669 . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 1. Dernière modification le 06 décembre 2016 à 14:06.
Certes, mais en même temps, exposer dans ta sérialisation le nom du membre (côté programme) est vraisemblablement une mauvaise idée.
Je comprends ta remarque, mais ce dont tu parles c'est d'avoir la possibilité de filtrer le "nom" des membres. L'un n'empêche pas l'autre. Dans 95% des cas, tu veux un 1:1 entre la sérialisation et ta classe, donc le code devrait pouvoir faire cela directement, et pour les 5% restant, tu peux intercepter et/ou filtrer. La proposition d'introspection (qui sera dans C++20 probablement) le permettra justement.
Ça c’est une très mauvaise idée. Si j’appelle un membre qui n’existe pas, je m’attends à une erreur de compilation, pas une erreur à l’exécution. Changer ça dans le contexte de C++, c’est, quelque part, casser le langage.
Justement, c'est tout l'intérêt du
constexprici. Par défaut, un tel opérateur entraînerait une erreur "membre machin non trouvé" donc le comportement sera 100% identique à l'état actuel.
Par contre, si l'opérateur est présent, alors soit il estconstexpret peut être vérifié à la compilation (donc un comportement entre le mode dynamique/runtime et le mode figé/statique).
Ceci serait très utile justement pour éviter les "outils" de génération qui écrivent du code illisible (type mock ou autre gsoap).
Exemple d'application, les membres namespace:attribute du XML, l'opérateur pourrait vérifier que le nom du membre "inconnu" que l'on veut vérifier commence par le nom du namespace attendu, par exemple.
Ou que les membres ajoutés commencent par "signal_" ou "slot_", si tu vois ce que je veux dire.Ensuite, si l'opérateur n'est pas constexpr, le compilateur pourrait te jeter pour chaque appel dont le nom du membre est fixe à la compilation (avec un warning du genre "Ce serait mieux si tu ajoutais un membre machin à ta classe").
Enfin, tu l'utilises comme une classe dynamique au runtime (donc tu ne connais pas le nom des membres à priori), et tu utilises l'introspection pour les retrouver. C'est faisable actuellement avec une table de hash, mais c'est pas natif, donc pas optimal.
En bref, tu as le choix, c'est justement ça pour moi l'intérêt principal du C++
-
[^] # Re: Nouveau langage
Posté par lmg HS (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 6. Dernière modification le 06 décembre 2016 à 11:51.
Ces paradigmes ne doivent pas être opposés. Ils offrent des choses complémentaires.
Et du coup, il faut combien de décennies d'apprentissage avant de savoir choisir le bon paradigme?
Combien de décennies faut-il pour savoir correctement concevoir? Je ne parle même pas de programmer, mais d'assimiler l'OO avec ses bonnes pratiques, le génie logiciel, la gestion des ressources, etc. Tout demande un investissement dans nos métiers—je sais que ce n'est pas ce que nos employeurs voudraient entendre.
Et pour savoir quoi choisir, la question, mes collègues savent toujours y répondre: est-ce un choix qui se fait à la compilation ? A l'exécution ? Au lancement ?
Après, j’admets volontiers que les choses deviennent compliquées quand on veut le beurre et l'argent du beurre. Exemple typique : un calcul sera appliqué sur des pixels d'images du spatial (en 10000x10000), mais la nature du calcul on ne la connait pas avant que l'utilisateur ne lance l'application. Là on veut un point de variation dynamique, et éviter de payer pour ce choix à l'exécution.
Je pense que personne ne considère qu'utiliser les conteneurs de la STL revient à faire de la programmation générique.
En termes de paradigmes, certains distinguent la programmation générique où l'on va utiliser, voire écrire des types génériques (comme on faisait en Ada sans que cela ne choque personne), et la métaprogrammation template où l'on va commencer à adapter automatiquement l'algorithme générique choisi en fonction des types que l'on manipule (p.ex. un tri sur une collection qui offre un accès direct et celui sur une collection qui n'offre qu'un accès séquentiel ne sera pas le même ;
std::copysur des POD pourra utilisermemcpy, etc).Les trucs les plus avancés que j'ai fait dans du code métier, c'est définir des listes de types décrivant des informations pouvant être extraites d'une trame binaire (ordre, nb bits dans la trame, type C++ associé après décodage). J'ai fait ça par métaprog. D'autres décrivent les trames en XML et font des parseurs compliqués, ou des générateurs de code. Dans tous les cas, un investissement est requis pour la technique employée.
Pour le fenouil braisé, on a des mécanismes similaires : l'envie de creuser, le temps, l’honnêteté d'admettre que c'est adapté (ou non!!) à une situation. Il y a beaucoup de critères. L'essentiel de ces critères est humains. Je renvoie à la première partie de la dernière présentation de Dan Saks au CppCon2016. Çà fait bien 20ans (plus?) qu'il essaie de vendre le typage supérieur à 0 surcoût du C++ avec template à la communauté C embarqué. Dans la première partie de la vidéo, il revient sur ce qui s'est passé et les raisons (humaines) de son échec.
Si ceux qui connaissent le C++ sont convaincus que la généricité peut s'importer facilement, voire plus facilement qu'un conception OO de qualité (combien ont compris SOLID et en particulier le LSP, et ce qu'est véritablement l'encapsulation? Trop peu.), pourtant ça bloque.
Tu me dis que ce n'est pas parce que ça (te) fait peur. Pourquoi alors ?
PS:
Truc<T>peut tout à fait hériter deITrucou deTrucImpl. C'est même assez classique quand on veut combiner une variabilité dynamique avec une statique. -
[^] # Re: Je m'y colle...
Posté par lmg HS (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 5.
Le SFINAE est un outil qui sert à détecter des informations non triviales ou des possibilités par essai et erreur. Sauf que les erreurs sont ignorées et à la place on se débrouille pour récupérer un truc que l'on va assimiler à faux. Ce booléen on s'en sert ensuite ailleurs pour choisir quelle spécialisation nous intéresse.
Exemple à la C++98
template <typename T> struct has_typedef_montype { using yes = char[1]; using no = char[2]; // Signatures qui renvoient des choses différentes // - Version qui prend ce que l'on cherche template <typename C> static yes& test(typename C::montype*); // - Version qui prend n'importe qui template <typename C> static no & test(...); // NB, on n'a pas besoin de définition, mais de renvoyer une réf. // Ici le compilo tente de résoudre. // Si T permet d'extraire un type `montype*`, alors on renvoie `yes` qui a une taille de 1 // Sinon, on défaulte sur la version variadique qui renvoie un `no` de taille 2 // Ce qui permet de construire le booléen `value` grâce à sizeof qui est toujours résolu à la compilation static const bool value = sizeof(test<T>(NULL))==sizeof(yes); }; struct U { using montype = int; }; int main () { std::cout << std::boolalpha; // affiche true ou false std::cout << has_typedef_montype<int>::value << "\n"; std::cout << has_typedef_montype<U>::value << "\n"; }Façon C++14 (voire 17), on a de nouveaux outils:
#if 0 // C++17 // Requiert gcc 5.0 template <typename...T> using void_t = void; #else // Pour gcc v < 5.0 // Until CWG 1558 (a C++14 defect), unused parameters in alias templates // were not guaranteed to ensure SFINAE and could be ignored, so earlier // compilers require a more complex definition of void_t, such as template<typename... Ts> struct make_void { typedef void type;}; template<typename... Ts> using void_t = typename make_void<Ts...>::type; #endif // Cas par défaut template <typename T, typename = void> struct has_typedef_montype : std::false_type {}; // Cas où l'on arrive à trouve le typedef qui nous intéresse template <typename T> struct has_typedef_montype<T, void_t<typename T::montype>> : std::true_type {}; -
[^] # Re: Je m'y colle...
Posté par Gabbro . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 1.
Merci à vous deux. Si j'ai bien compris, SFINAE, c'est simplement l'idée d'aller chercher la fonction la plus spécialisée ; ça me fait penser au
select typedu fortran 2003.Pour le
constexpr, de ce que je lisais sur les sites donnés, il n'y a même pas besoin de template. C'est juste un moyen simple de pré-calculer des valeurs, tout en les calculant à l’exécution lorsque c'est impossible à la compilation. -
[^] # Re: Je m'y colle...
Posté par Morovaille . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 6. Dernière modification le 06 décembre 2016 à 10:05.
C'est de la programmation fonctionnelle à la compilation. Un bon exemple est la fonction factorielle.
Tu définis une structure
factorialqui dépend d'un paramètre template qui est un entier :template <std::size_t N> struct factorial { };À l'intérieur tu définis le cas général :
static constexpr std::size_t value = RangeN * factorial<RangeN - 1>::value;constexprveut dire que c'est calculé à la compilation. C'est faisable puisqu'on a toutes les infos à la compilation. Le code est simple,valueest égal au rang actuel multiplié par factorielle du rang moins un.Comme dans toute programmation récursive (la programmation fonctionnelle se fait en récursion), il faut une condition d'arrêt :
template<> struct factorial<0u> { constexpr static std::size_t value = 1u; };La valeur de factorielle de 0 est un. C'est ici que la récursion s'arrête.
Un programme complet pour montrer le code :
#include <iostream> template <std::size_t RangeN> struct factorial { static constexpr std::size_t value = RangeN * factorial<RangeN - 1>::value; }; template<> struct factorial<0u> { constexpr static std::size_t value = 1u; }; int main() { std::cout << factorial<0>::value << "\n"; std::cout << factorial<4>::value << "\n"; }factorial<0>::valueetfactorial<4>::valuesont connus à la compilation, rien n'est calculé au runtime.Cet exemple là n'est pas très utile, mais il existe des cas où ces technique améliorent beaucoup la rapidité du code en précalculant des choses à la compilation. Glander sur http://stackoverflow.com/questions/tagged/metaprogramming%20c%2b%2b peut donner quelques exemples d'application.
Ce commentaire est libre de droit, vous pouvez le réutiliser comme bon vous semble.
-
[^] # Re: Nouveau langage
Posté par xcomcmdr . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 2.
C'est pas bien de ramener les gens à la réalité. :-p
"Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)
-
[^] # Re: Je m'y colle...
Posté par Gof (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 2.
Pas facile en effet de trouver de bonnes explication en français de SFINAE. Google me donne ceci: http://h-deb.clg.qc.ca/Sujets/Divers--cplusplus/SFINAE.html
Est-ce que ça aide ?j'ai pas mal entendu parlé de template et de métaprogrammation, mais je n'ai jamais compris ce que c'était (ni à quoi ça sert).
Le problème n'est peut être pas SFINAE, mais la métaprogrammation tout court.
Quelques liens:
http://loulou.developpez.com/tutoriels/cpp/metaprog/
http://h-deb.clg.qc.ca/Sujets/Divers--cplusplus/Metaprogrammation.html -
[^] # Re: Nouveau langage
Posté par jcelerier . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 1. Dernière modification le 06 décembre 2016 à 00:14.
En attendant, on peut tricher un peu en faisant ça :
#include <boost/unordered_map.hpp> #include <variant> struct js_object; using js_value_t = std::variant<int, std::string, bool, js_object>; struct js_object { template<int N> constexpr void set(const char (&s)[N], const js_value_t& value) { if ( str_equal(s, "foo") ) { m_foo = std::get<int>(value); } else if ( str_equal(s, "the_bar") ) { m_bar = std::get<int>(value); } else { m_other[s] = value; } } template<int N> constexpr js_value_t get(const char (&s)[N]) const { if ( str_equal(s, "foo") ) { return m_foo; } else if ( str_equal(s, "the_bar") ) { return m_bar; } else { return m_other.at(s); } } private: template<int N, int M> static constexpr bool str_equal(const char (&s)[N], const char (&s2)[M]) { if constexpr (N == 0 || N != M) return false; for(int i = 0; i < N; i++) { if (s[i] != s2[i]) return false; } return true; } int m_foo = 0; int m_bar = 0; boost::unordered_map<std::string, js_value_t> m_other; }; auto my_function(js_object& b) { b.set("the_bar", 1111); return std::get<int>(b.get("the_bar")); } auto other_function(js_object& b) { using namespace std::literals; b.set("random_value", "a string"s); }Avec GCC à -O3,
my_functionse simplifie.
my_function(js_object&):
mov DWORD PTR [rdi+4], 1111
mov eax, 1111
ret -
[^] # Re: Nouveau langage
Posté par arnaudus . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 10.
Ces paradigmes ne doivent pas être opposés. Ils offrent des choses complémentaires.
Et du coup, il faut combien de décennies d'apprentissage avant de savoir choisir le bon paradigme?
pour gérer la mémoire, par défaut je vais utiliser des unique_ptr<> qui sont génériques.
Je pense que personne ne considère qu'utiliser les conteneurs de la STL revient à faire de la programmation générique.
Je comprends que devoir écrire ce genre de classe from scratch fasse peur à quelqu'un qui n'est pas habitué
Je n'aime pas le fenouil braisé. Est-ce que ça veut dire que j'ai peur du fenouil braisé? Est-ce légitime de m'expliquer que la seule raison pour laquelle je n'aime pas le fenouil braisé est que je n'y suis pas habitué? Au bout d'un moment, c'est agaçant.
Reste que ce ne sont pas des paradigmes opposés.
Si, parce qu'ils sont incompatibles, et qu'ils répondent tous les deux au même besoin de base (utiliser le même code pour appliquer les mêmes opérations à des objets différents qui partagent un certain nombre de propriétés). Si on va au-delà des simples conteneurs style STL, on se retrouve avec des possibilités d'architectures parallèles (d'un côté,
Truc<A>etTruc<B>, d'un autre côté TrucA et TrucB qui dérivent de Truc), avec chacun leurs paradigmes, leur syntaxe, leurs contraintes et leurs avantages. Mélanger les deux dans un projet un peu complexe me semble assez incongru, au moins autant que de mélanger des paradigmes C et C++, par exemple. -
[^] # Re: Nouveau langage
Posté par Oliver (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 6.
Par exemple, la fonction suivante ne fonctionne que pour les structures (classes) fournissant des fonctions membres
recupere_x()etrecupere_y().template <typename T> auto calcule (T objet) { auto x = objet.recupere_x(); auto y = objet.recupere_y(); return (x+x) - (y*y); }Supposons que nous devions utiliser deux bibliothèques développées par deux entités différentes :
- Un bibliothèque fournit une structure (classe) qui ne possède pas les fonctions membres
recupere_x()etrecupere_y(); - La seconde bibliothèque fournit la fonction
calcule.
On n'a pas la possibilité de modifier aucune des deux bibliothèques.
Comment faire pour passer la structure (classe) à la fonctioncalcule?Voyons maintenant, une implémentation de la fonction
calculeutilisant cette fois-ci les fonctions libres :template <typename T> auto calcule (T objet) { auto x = recupere_x(objet); auto y = recupere_y(objet); return (x+x) - (y*y); }Et c'est beaucoup plus facile de passer la structure (classe) à la fonction
calcule(). Deux possibilités :- les fonctions libres
recupere_x()etrecupere_y()sont déjà disponibles dans une bibliothèque ; - ou bien nous devons les implémenter, ce qui est bien plus facile que l'exercice précédent.
C'est dans ce second paradigme que sont conçus beaucoup de langages récents comme Rust et Go.
Cela permet naturellement de respecter le principe ouvert/fermé.Prenons un exemple dans un vieux langage... allez prenons Python qui doit avoir une trentaine d'années, et étudions sa fonction libre
len():str = 'test' r = len(str) # retourne 4Certains objets implémentent la fonction membre
__len__()mais la convention est de passer par la fonction librelen().Commentaire sous licence Creative Commons Zero CC0 1.0 Universal (Public Domain Dedication)
- Un bibliothèque fournit une structure (classe) qui ne possède pas les fonctions membres
-
[^] # Re: Nouveau langage
Posté par Meku (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 2.
Quel est le problème avec les fonctions membres, ou plutôt, pourquoi les fonctions libres seraient-elles mieux ?
-
[^] # Re: Je m'y colle...
Posté par Gabbro . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 4.
N'ayant pas compris un traitre mot du lien ci-dessus, je suis favorable à un article, ou un autre lien qui supposerait moins de connaissance de la part du lecteur.
Parce que j'ai pas mal entendu parlé de
templateet de métaprogrammation, mais je n'ai jamais compris ce que c'était (ni à quoi ça sert). -
[^] # Re: Nouveau langage
Posté par doom_Oo7 . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 2.
Ça c’est une très mauvaise idée. Si j’appelle un membre qui n’existe pas, je m’attends à une erreur de compilation, pas une erreur à l’exécution. Changer ça dans le contexte de C++, c’est, quelque part, casser le langage.
C'est bien pour ça que ça devrait être quelque chose d'implémentable côté bibliothèque.
Je pense qu'un des avantages du C++ c'est que faire des choix dans son code, ce n'est pas "casser le langage". Le langage nous offre des briques, et on est libre de construire ce que l'on veut avec. Avoir plus de briques n'est jamais une mauvaise chose, on est toujours libre de les laisser dans le bac à legos... mais par contre on peut toujours sortir la brique le jour ou on en a besoin (et j'ai déjà eu besoin plus d'une fois explicitement de cette fonctionnalité... c'est toujours possible de le refaire à la main ou avec des templates variadiques si on est motivé, mais bon).
-
[^] # Re: Correction § "Remplacement du SFINAE"
Posté par Benoît Sibaud (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 2.
Corrigé, merci.
-
[^] # Re: Je m'y colle...
Posté par barmic . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 3.
Oui c'est pour ça que je ne vois pas trop pourquoi en faire un article (avec 2 articles d'introduction en plus !).
Mais je rate probablement quelque chose...Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
-
[^] # Re: Nouveau langage
Posté par lmg HS (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 6.
Ces paradigmes ne doivent pas être opposés. Ils offrent des choses complémentaires. Si je dois gérer mes observateurs à la main, je vais utiliser les classes génériques standards. Ne pas le faire serait totalement idiot de ma part.
Pareil, pour gérer la mémoire, par défaut je vais utiliser des
unique_ptr<>qui sont génériques. Et je les mettrai dans des objets.Je comprends que devoir écrire ce genre de classe from scratch fasse peur à quelqu'un qui n'est pas habitué à la lourdeur de la syntaxe et à qui l'école n'a appris qu'un bout de l'OO (pour factoriser des données de bases de données et non pas pour factoriser des comportements) et du procédural. Mais pour la majorité d'entre nous, on n'a rien de tel à écrire. Juste à utiliser.
Reste que ce ne sont pas des paradigmes opposés.
Je dirai aussi, que le mélange est tout sauf récent. Cf la Thèse de Jim O Coplien qu'il a ultérieurement édité en livre: Multiparadigm Design in C++—cf la FAQ de dvpz pour les liens. Un des aspects les plus intéressants, c'est toute la partie sur la dualité commonalities et variability points. C'est le B à ba. On a des zones de code communes, et dedans, il y a des points où des détails vont varier. Et ça on sait le faire depuis longtemps: socket win32 ou socket POSIX ? Tableau d'entiers ou tableau de doubles ? Affichage de carrés, cercles, polygones ou autre figure géométrique ?
Toute la question est la dynamicité derrière les points de variations—et leur potentielle capacité à évoluer sans requérir de modification. Est-ce quelque chose que l'on sait déterminer dans le code source ? En fonction de la plateforme de build ? Est-ce lié à des plugins (choix du .so à charger)? Est-ce totalement dynamique ? Et bien en fonction de ça, ou va jouer avec des
#if, on va compiler un .c ou un autre, on va avoir des instances d'un type ou d'un autre, ou on va choisir le paramètre template d'un type générique.Bref. C'est juste un autre levier qui offre plus de finesse. Et dans un même projet, il peut être intéressant de disposer de plusieurs façons pour procéder.
-
[^] # Re: Je m'y colle...
Posté par Morovaille . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 1.
Hum, en fait je crois que comme M. Jourdain qui faisait de la prose sans le savoir je faisais de la SFINAE. C'est une des bases de la métaprogrammation en fait, tout simplement. Si on en a fait un tout petit peu, on a forcément exploité cette technique.
Ce commentaire est libre de droit, vous pouvez le réutiliser comme bon vous semble.
-
[^] # Re: Je m'y colle...
Posté par whity . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 3.
En attendant, il y a une explication relativement claire en français ici.
Mes commentaires sont en wtfpl. Une licence sur les commentaires, sérieux ? o_0
-
# SFINAE
Posté par OhMyGod . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 1.
Deux vidéos intéressantes sur la metaprogrammation et les SFINAE :
CppCon 2014: Walter E. Brown "Modern Template Metaprogramming: A Compendium (partie 1 et 2)
https://www.youtube.com/watch?v=Am2is2QCvxY
https://www.youtube.com/watch?v=a0FliKwcwXE -
[^] # Re: Retour arrière sur l'OCP
Posté par whity . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 1.
Je ne suis pas trop d’accord avec toi (du moins, avec ce que tu as écris). Tu donnes l’impression que ouvert et fermé s’opposent, alors que dans l’OCP, ils se complètent (n’agissent pas sur la même dimension). L’article wikipédia en français est assez clair là-dessus.
La complexité du code n’a pas nécessairement grand chose à voir là-dedans (au contraire, bien mis en œuvre, l’OCP a tendance à simplifier l’architecture globale car il réduit les effets de bord).
Mes commentaires sont en wtfpl. Une licence sur les commentaires, sérieux ? o_0
-
[^] # Re: Nouveau langage
Posté par arnaudus . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 4.
Je pense qu'en 2017 nous publierons de petites dépêches pour expliquer les aspects de la programmation générique et surtout la méta-programmation (et un peu de programmation fonctionnelle) car c'est l'intérêt de coder en C++.
Bah, je n'ai rien personnellement contre la programmation générique. C'est juste que le C++ OO et le C++ générique ressemblent de plus en plus à deux dialectes distincts, au moins autant que le C et le C++98. Et s'il est techniquement possible de mélanger les deux (le compilateur le comprend), c'est de plus en plus compliqué de les faire cohabiter dans le même projet. Mon impression est que de toutes manières les programmeurs ne vont plus pouvoir s'en sortir avec les deux paradigmes à la fois; d'un côté on aura le monde des design patterns et du typage dynamique, et de l'autre côté on aura les templates de templates et le typage statique.
Par contre, du coup, appeler tout ça "C++" et continuer à prétendre que c'est le même langage, ça n'est pas très sain. Pour recruter quelqu'un dans une boîte ou dans un projet, il va falloir préciser quels aspects du C++ on souhaite privilégier. De même, il pourrait être sympa de commencer à définir des sous-ensembles plus ou moins officiels qu'on pourrait passer aux compilateurs, pour vérifier qu'on respecte bien le cadre imposé. J'ai appris il y a peu de temps que pour émuler ce comportement, certains n'acceptaient que d'anciennes versions des compilateurs, ce qui me semble profondément stupide (on peut ne pas vouloir autre chose que du C++98 tout en voulant profiter des corrections de bugs et des optimisations des compilos récents).
Le mot-clé template fait peur, démystifions-le ;-)
Je ne pense pas que ça soit les templates qui fassent peur, c'est l'ensemble pas très intuitif des syntaxes associées.
-
[^] # Re: Syntaxe ?
Posté par Oliver (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 2. Dernière modification le 05 décembre 2016 à 15:59.
Petite précision : Si le
static_assert()devait être introduit aujourd'hui dans le C++ il aurait été renommé enconstexpr_assert()car en C++ on essaye de faire la distinction entre la (les) sémantique(s) portée(s) par le mot-cléstaticet celle deconstexpr.Commentaire sous licence Creative Commons Zero CC0 1.0 Universal (Public Domain Dedication)
-
[^] # Re: Je m'y colle...
Posté par Oliver (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 3. Dernière modification le 05 décembre 2016 à 15:45.
OK on rajoute ça dans le tuyau ;-)
On commencera par quelques petites dépêches sur la méta-programmation, puis on attaquera gentiment le SFINAE ^
Mais soit patient, ça risque d'être pour l'année prochaine !Commentaire sous licence Creative Commons Zero CC0 1.0 Universal (Public Domain Dedication)
-
# Je m'y colle...
Posté par windu.2b . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 10.
Chère lectrice, cher lecteur LinuxFr.org. Souhaites-tu une dépêche consacrée au SFINAE ? Alors exprime-toi dans les commentaires, et de nombreuses personnes vont certainement unir leur forces pour t’offrir un superbe article sous licence libre. Bon, si tu n’oses pas demander, personne n’aura l’impulsion pour se lancer...
Puisqu'il faut demander, je m'y colle : on pourra avoir une dépêche sur le SFINAE ? Parce que j'ai à peu près rien compris ! Comme ça, je n'aurai sans doute toujours rien compris, mais j'aurai plus à lire ! :-)
-
[^] # Re: Syntaxe ?
Posté par lmg HS (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 1.
Sauf si le nouveau truc est un mot clé.
Imagine une bibliothèque pré C++11 avec unmy::constexpr. En C++11, ça ne peut plus compiler. -
# Correction § "Remplacement du SFINAE"
Posté par Oliver (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 3. Dernière modification le 05 décembre 2016 à 15:09.
Le code suivant est utilisé dans la dépêche, mais il est ambigu car on ne voit pas la différence au niveau de la déclaration des deux fonctions :
template<class T> auto f(T x) -> decltype(std::enable_if_t<std::is_function_v<decltype(T::f)>,int>{}) { return x.f(); } template<class T> auto f(T x) -> decltype(std::enable_if_t<!std::is_function_v<decltype(T::f)>,int>{}) { return 0; }Merci à un modérateur de le remplacer par :
template<class T> auto f(T x) -> decltype(std::enable_if_t< std::is_function_v<decltype(T::f)>,int>{}) { // ^---true si T::f existe et que c'est une fonction return x.f(); } template<class T> auto f(T x) -> decltype(std::enable_if_t< ! std::is_function_v<decltype(T::f)>,int>{}) { // ^---le contraire return 0; }Commentaire sous licence Creative Commons Zero CC0 1.0 Universal (Public Domain Dedication)
-
[^] # Re: Retour arrière sur l'OCP
Posté par Oliver (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 3. Dernière modification le 05 décembre 2016 à 15:00.
C'est le principe ouvert/fermé.
Connu en anglais sous le nom open/closed principle.
(dans notre cas du C++, je trouve plus explicite le commentaire de lmg HS que l'article Wikipédia)Souvent, on préfère un code simple et fermé à à code complexe mais ouvert (évolutif).
L'idée est d'avoir un code simple, facile à comprendre, et le jour où on a vraiment besoin de le faire évoluer, et bien on le réécrit.
Le risque d'avoir un code complexe mais ouvert est de garder la complexité et de ne jamais profiter de son ouverture.Je précise, je suis pour le principe ouvert/fermé. Je dis juste que des fois (voir souvent) ce n'est pas justifié.
Selon le contexte, on utilisera :
-
if constexprpour du code simple et fermé ; - plusieurs templates pour du code complexe mais ouvert.
Commentaire sous licence Creative Commons Zero CC0 1.0 Universal (Public Domain Dedication)
-
-
[^] # Re: Syntaxe ?
Posté par Chuck #1 . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 1.
Normalement, chaque bibliothèque a son espace de nommage donc ça ne plante que si on utilise la bibliothèque comme un goret (cf. le std:: devant les fonctions de la bibliothèque standard).
Cette signature est publiée sous licence WTFPL
-
[^] # Re: Nouveau langage
Posté par whity . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 3.
Il n'y a pas une seule bibliothèque C++ aujourd'hui qui sache faire de la sérialisation sans avoir à déclarer chaque champs 2 fois (une fois pour la compilation "statique" et une fois pour le runtime). C'est assez pénible.
Certes, mais en même temps, exposer dans ta sérialisation le nom du membre (côté programme) est vraisemblablement une mauvaise idée. Outre que suivant le type de sérialisation voulue, celui ci peut nécessiter une transformation (par exemple, pour sérialiser vers xml, on aura tendance à transformer les « _ » en « - » ). Donc devoir le définir deux fois mais pas à proprement parler un soucis, en tout cas pas majeur.
De plus, si les objets sont simplement des conteneurs sans intelligence (par exemple, des objets correspondant à des enregistrements dans une base SQL), le code est souvent généré automatiquement.
Lorsque le compilateur rencontrerait un membre non présent, il appellerait l'opérateur "." (qui peut static_asserter si le nom n'est pas acceptable, ou remplir les champs au runtime.
Ça c’est une très mauvaise idée. Si j’appelle un membre qui n’existe pas, je m’attends à une erreur de compilation, pas une erreur à l’exécution. Changer ça dans le contexte de C++, c’est, quelque part, casser le langage.
Mes commentaires sont en wtfpl. Une licence sur les commentaires, sérieux ? o_0
-
[^] # Re: Nouveau langage
Posté par xryl669 . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 1.
Je suis tout à fait d'accord. Concernant la POO, le standard C++17 n'apporte rien de transcendant. Franchement, avoir des fonctionnalités d'introspection en 2017, je ne pense pas que ce soit si superflu (à l'heure où quasiment toute donnée est transmise en JSON). Il n'y a pas une seule bibliothèque C++ aujourd'hui qui sache faire de la sérialisation sans avoir à déclarer chaque champs 2 fois (une fois pour la compilation "statique" et une fois pour le runtime). C'est assez pénible.
De même, avoir des objets dynamiques, sans se taper des tuple à rallonge qui sont vraiment mauvais niveau praticité et performance et maintenabilité, à part pour la performance, c'est franchement manquant. Alors qu'il suffirait d'ajouter un opérateur pour "membre non trouvé" à gérer au runtime, du genre
struct MyClass { int foo; string bar; runtime_members __otherMembers; // A bit like a map<any> template <class T> any operator .(const string & name, const T & arg ) { return __otherMembers[name] = arg; } }; MyClass a; a.foo = 3; a.bar = "hello"; a.baz = "world"; // call operator . a.qux = 4.5; // dittoLorsque le compilateur rencontrerait un membre non présent, il appellerait l'opérateur "." (qui peut static_asserter si le nom n'est pas acceptable, ou remplir les champs au runtime.
-
[^] # Re: Retour arrière sur l'OCP
Posté par lmg HS (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 0.
s/tour/retour
-
# Retour arrière sur l'OCP
Posté par lmg HS (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 3.
Si cette évolution va simplifier l'écriture de fonctions récursives telles que les templates variadiques comme montré en exemple dans la dépêche, je redoute pour ma part un tour arrière sur le principe ouvert (aux évolutions) fermé (aux modifications).
Souvenez-vous, c'est le principe qui dit que dans un monde OO, les
ifc'est mal, et que les fonctions virtuelles c'est mieux. L'idée est que quand nous identifions des points de variations, plutôt que de modifier le code pour ajouter des nouveaux cas à coups deifou deswitch, à la place, on prévoit un point de variation ouvert qui pourra accepter de façon plug-and-play des nouveaux cas non encore identifiés/définis.Si l'OO nous offrait un OCP dynamique, jusqu'à présent on employait des traits ou le SFINAE (c'est pas vraiment des traits le SFINAE) en métaprogrammation template. Pour ceux qui connaissent le Prolog (voire XSLT), on retrouve quelques part le principe de résolution par unification.
C'est sûr qu'un
ifc'est plus simple et plus accessible. Mais c'est beaucoup moins évolutif. -
[^] # Re: Nouveau langage
Posté par lmg HS (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 3.
Parenthèse: A.Stepanov se défend que la STL historique ait été conçue OO. Il y a diverses vidéos sur le sujet.
Dans le cas de
v.begin()il sous-entend dans son Notes on Programming que pour passer le véto de l'intelligentzia OO qui n'avait pas encore migré vers d'autres langages à l'époque (le subjectif dans le phrasé est mien), il avait dû concéder à faire desize& cie des fonctions membres et non des fonctions libres. Depuis le C++11 on corrige le tir. Il faut attendre C++17 pour avoirstd::size()—même s'il est facile à écrire dès le C++11: c'est un oubli.A noter aussi les propositions autour du Uniform Call Syntax par Stroustrup et d'autres qui n'ont pas été retenues pour le C++17—j'avais donné le lien dans les commentaires d'une précédente dépêche vendredi.
-
[^] # Re: Syntaxe ?
Posté par lmg HS (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 4.
Une question facile :)
En C++, quand il s'agit d'ajouter quelque chose, ils cherchent avant toute chose à n'ajouter aucun nouveau mot clé. L'objectif est de n'introduire aucune régression sur des vieux codes qui compilaient. Ce qui fait que les évolutions se font en priorité dans la bibliothèque standard, puis par réutilisation/dépréciation de mots clés (cf
auto).Avec
static_if, il suffit d'une bibliothèque tierce (et je crois bien qu'il en existe justement) qui définit quelque chose avec ce nom, et cela plante définitivement la bibliothèque et tous les codes qui s'en servent. -
# Syntaxe ?
Posté par whity . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 3.
Merci pour cette dépêche. Je suis un peu surpris par la syntaxe choisie. Je me serais attendu à quelque chose comme
static_if<cond> {un peu sur le modèle du
static_assert.Quelqu’un sait ce qui a motivé le choix de cette syntaxe ?
Mes commentaires sont en wtfpl. Une licence sur les commentaires, sérieux ? o_0
-
[^] # Re: Nouveau langage
Posté par Oliver (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 5.
Oui, tout à fait.
Au début (il y a une quarantaines d'années), le C++ s’orientait exclusivement vers la Programmation Orientée Objet (POO).
Mais, depuis C++11, le C++ évolue dans d'autres directions :
- Faciliter la programmation générique (avec les variadique par exemple) ;
- Faciliter la méta-programmation (avec
static_assert,constexpr...) ; - ...
-
Et se passer aussi de la POO quand c'est possible, exemples :
a.begin() -> std::begin(a) a.size() -> std::size(a)
Si nous regardons les nouveaux langages comme Go ou Rust, nous voyons bien que la POO n'est plus à la mode.
Je pense qu'en 2017 nous publierons de petites dépêches pour expliquer les aspects de la programmation générique et surtout la méta-programmation (et un peu de programmation fonctionnelle) car c'est l'intérêt de coder en C++. Le mot-clé
templatefait peur, démystifions-le ;-)Commentaire sous licence Creative Commons Zero CC0 1.0 Universal (Public Domain Dedication)
-
[^] # Re: Nouveau langage
Posté par Benbben . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 4.
Ça va devenir de plus en plus compliqué de définir ce qu'est le C++, puisqu'au final quelque chose comme "le logiciel est codé en C++" ne voudra plus dire grand chose, à part qu'il est compilable par un compilateur C++.Si je me fie à la précédente dépêche sur l'ordre d'évaluation des prédicats. L'objectif est de passer de "le logiciel est codé en C++ => c'est de la POO." à "le logiciel est codé en C++ => il est compilable par un compilateur C++ et son comportement sera le même et prévisible quelques soit le compilateur utilisé."
Ce qui me semble une bonne idée.
-
# Nouveau langage
Posté par arnaudus . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 10.
D'abord, merci pour cette série d'articles, c'est assez agréable de pouvoir passer 5 minutes à lire quelque chose d'assez compact sur chaque nouveauté plutôt qu'une énorme dépêche ultra-résumée.
Sur le fond, quand je lis le code proposé, je me dis quand même qu'on est carrément en train de définir un nouveau langage avec la programmation générique. Je n'ai pas l'intention de résoudre en un commentaire la discussion éternelle sur le fait que C++ est ou n'est pas un langage orienté objet, mais mon point de vue est quand même que le multi-paradigme a une limite, c'est celle de la compréhension croisée entre les différents programmeurs.
Concrètement, j'ai un mal fou à discuter avec les «petits jeunes» qui apprennent la syntaxe générique du C++, parce que j'ai quand même l'impression que pour beaucoup d'applications, la programmation OO et la programmation générique permettent de faire des choses qui se superposent largement, mais qui sont assez incompatibles. On peut partir sur un design à base de templates ou sur un design à base de hiérarchies de classes, et une fois ce choix fait, on a quasiment deux dialectes incompatibles. Ça va devenir de plus en plus compliqué de définir ce qu'est le C++, puisqu'au final quelque chose comme "le logiciel est codé en C++" ne voudra plus dire grand chose, à part qu'il est compilable par un compilateur C++.