Sommaire
Le design pattern du Visiteur est un des plus connu. Il permet, selon Wikipédia, de «séparer un algorithme d'une structure de données». Je ne rappelle pas l'intérêt de ce design pattern, j'en viens directement au fond de cet article : quelle est la meilleure façon de faire un Visiteur en C++ ? Il y a essentiellement deux manières, et une variante sur la deuxième, avec chacune leurs avantages et inconvénients.
Le Visiteur polymorphe
C'est la manière la plus simple et celle qu'on rencontre partout (comme sur l'article Wikipédia). Voilà comment ça se présente sur un petit exemple.
class Visitor;
class Base {
public:
virtual void accept(Visitor& vis) {
vis.visitBase(*this);
}
};
class Derived : public Base {
public:
virtual void accept(Visitor& vis) override {
vis.visitDerived(*this);
}
};
class Visitor {
virtual void visitBase(Base& b) {
}
virtual void visitDerived(Derived& d) {
}
};
Du classique. Ensuite, quand on veut utiliser un Visiteur, on dérive de Visitor
et hop, ça marche. Je ne détaille pas les avantages/inconvénients tout de suite.
Le Visiteur template
Pour ceux qui n'aiment pas le polymorphisme (qui est quand même l'essence de l'OO), C++ permet de faire un Visiteur avec des templates. Ce code est inspiré de LLVM (qui utilise la variante présentée ensuite) qui utilise des Visiteurs pour quasiment tout.
Le Visiteur template à base de RTTI
L'idée est simple : remplacer le dispatch du accept
par une suite de condition vérifiant le type de l'objet dynamiquement. Pour cela, on va utiliser l'opérateur typeid
qui permet de récupérer un objet de type type_info
qu'on peut comparer à un autre objet de type type_info
. Quand les objets sont simples (sans méthode virtuelle), le type_info
peut être calculé à la compilation. Dès que l'objet possède une méthode virtuelle (le destructeur par exemple), le type_info
est déterminé à l'exécution.
class Base {
public:
virtual ~Base() { } // on met une fonction virtuelle pour rendre typeid dynamique
void accept(Visitor& vis) {
if (typeid(*this) == typeid(Derived)) {
vis.visitDerived(static_cast<Derived&>(*this));
return;
}
vis.visitBase(*this);
}
};
class Derived : public Base {
// pas besoin de code dans les classes filles
};
Reste un problème : en l'état actuel, le Visiteur doit encore être déclaré comme précédemment, avec du polymorphisme. C'est là qu'intervient le template. Il est impossible en C++ de déclarer une méthode virtuelle avec un template (heureusement !), mais ici, notre méthode accept
n'est plus virtuelle, donc on peut lui coller un template.
template<typename Visitor>
void accept(Visitor& vis) {
if (typeid(*this) == typeid(Derived)) {
vis.visitDerived(static_cast<Derived&>(*this));
return;
}
vis.visitBase(*this);
}
Cette fois, c'est gagné, on peut déclarer n'importe quel visiteur sans devoir hériter d'un visiteur père.
class FooVisitor {
void visitBase(Base& b) {
}
void visitDerived(Derived& d) {
}
};
On doit cependant déclarer toutes les méthodes requises. Inutile de créer un Visiteur père avec des implémentations par défaut, ça ne marchera pas. Au moment de l'instanciation, le compilateur n'ira pas chercher dans la classe mère. Pour pallier ce problème, on peut modifier un peu notre Base et notre Visiteur et placer la logique de dispatch dans le Visiteur.
class Base {
public:
virtual ~Base() { }
template<typename Visitor>
void accept(Visitor& vis) {
vis.visit(*this);
}
};
class Derived : public Base {
};
template<typename Subclass>
class Visitor {
public:
void visit(Base& base) {
if (typeid(base) == typeid(Derived)) {
static_cast<Subclass*>(this)->visitDerived(static_cast<Derived&>(base)); // Ouch !
return;
}
static_cast<Subclass*>(this)->visitBase(base);
}
// les implémentations par défaut
void visitBase(Base& b) {
}
void visitDerived(Derived& d) {
}
};
Un peu d'explication sur la ligne Ouch. Déjà, on a un argument template pour ce visiteur. Quand on implémentera un visiteur, il faudra dériver de celui-ci de la manière suivante :
class FooVisitor : public Visitor<FooVisitor> {
// ...
};
Ça permet de prévenir Visitor
de sa classe fille et donc de faire appel aux méthodes de la classe fille en castant this
en Subclass
. Comme on appelle visit
depuis l'objet, on peut faire le dispatch dans le visiteur et appeler les méthodes utiles du Visiteur à ce moment-là. Ensuite, dans les Visiteurs (comme FooVisitor
), on implémente uniquement les méthodes nécessaires et pas toutes les méthodes.
Avantages et inconvénients
Évidemment, tout est histoire de compromis. Passons donc en revue les avantages et inconvénients de chaque technique.
Du côté des avantages pour les templates, on peut citer le découplage entre le Visiteur et la structure, dans le sens où on n'a plus de cycle de dépendance entre Visitor
et Base
. Autre avantage, si on ajoute une classe dans la hiérarchie et qu'on n'a pas mis de méthode par défaut, on tombera dans le cas de Base
. Ce cas ne sera sans doute pas pertinent, mais ça compilera. Avec le Visiteur polymorphe, il faudra ajouter la méthode adéquate dans le visiteur sinon, ça ne compilera pas.
Du côté des inconvénients, un petit test rapide montre que le Visiteur avec template est environ 3 fois plus lent que le Visiteur polymorphe. C'est là qu'intervient la variante pour améliorer ce manque de performance.
Le Visiteur template sans RTTI
Ce qui prend du temps, c'est le RTTI, c'est-à-dire tous les appels à typeid
. Il est possible de mimer un genre de typeid en ajoutant un membre à Base
qui sera initialisé dans les constructeurs.
enum Kind { BASE, DERIVED }
class Base {
public:
const Kind kind;
Base(Kind k) : kind(k) { } // pour les classes filles
Base() : kind(BASE) { } // pour la classe Base
// ...
};
class Derived : public Base {
public:
Derived() : Base(DERIVED) { }
};
Ça alourdit un peu le code mais ça permet de se passer du RTTI. Du côté du Visiteur, on peut faire un simple switch
:
template<typename Subclass>
class Visitor {
public:
void visit(Base& base) {
switch (base.kind) {
case DERIVED:
static_cast<Subclass*>(this)->visitDerived(static_cast<Derived&>(base)); // Ouch !
return;
case BASE:
static_cast<Subclass*>(this)->visitBase(base);
}
}
// ...
};
Avec cette astuce, on n'arrive pas tout à fait à la performance du Visiteur polymorphe mais on s'en approche à moins de 10%, ce qui est tout à fait convenable.
Les petits plus
LLVM, en plus de cette technique, introduit deux petits plus dont le premier n'est pas reproductible dans le cas du Visiteur polymorphe. Il s'agit de faire varier le type de retour du Visiteur. Actuellement, on a mis void
. Mais on peut faire mieux et mettre le type de retour dans le template du visiteur.
class Base {
public:
// ...
template<typename Visitor>
typename Visitor::return_type accept(Visitor& vis) {
return vis.visit(*this);
}
};
template<typename Subclass, typename RetTy>
class Visitor {
public:
typedef RetTy return_type;
return_type visit(Base& base) {
switch (base.kind) {
case DERIVED:
return static_cast<Subclass*>(this)->visitDerived(static_cast<Derived&>(base)); // Ouch !
case BASE:
return static_cast<Subclass*>(this)->visitBase(base);
}
}
return_type visitBase(Base& b) {
return return_type();
}
return_type visitDerived(Derived& d) {
return return_type();
}
};
On peut maintenant faire des visiteurs qui renvoie des entier ou tout autre type. Dans le cas du Visiteur polymorphe, on peut passer par un membre mais c'est moins joli.
Autre petit plus inspiré de LLVM et qui là, peut tout à fait s'appliquer au Visiteur polymorphe. Généralement, on ne visite que les feuilles de l'arbre des classes et pas les classes abstraites. LLVM permet de visiter également une classe abstraite et, dans les implémentations par défaut, le visiteur appelle la méthode pour sa classe mère (éventuellement abstraite). Cette astuce permet de mutualiser certains traitements à toute une hiérarchie.
template<typename Subclass, typename RetTy>
class Visitor {
public:
typedef RetTy return_type;
// ...
return_type visitBase(Base& b) {
return return_type();
}
return_type visitDerived(Derived& d) {
return visitBase(d);
}
};
Conclusion
Voilà, le voyage dans le fabuleux monde des visiteurs C++ est fini. En conclusion, on peut dire qu'il n'y a pas un vainqueur net, mais qu'il faut adapter le type de Visiteur au projet.
# Utilité ?
Posté par reynum (site web personnel) . Évalué à 9.
Dommage ça aurait pu rafraîchir la mémoire de pas mal de gens (moi le premier) !
Pffff obligé de faire une recherche tout seul !! vie de m…
Sinon, merci pour ce journal intéressant.
kentoc'h mervel eget bezan saotred
[^] # Re: Utilité ?
Posté par bibitte . Évalué à 0.
C'est pas comme si son premier lien pointe sur wikipedia…
A ta décharge il pointe sur http://fr.wikipedia.org/wiki/Visiteur (liste des articles "visiteur")au lieu de pointer directement sur http://fr.wikipedia.org/wiki/Visiteur_%28patron_de_conception%29 mais un clic de plus c'est pas si dur non ?
# "Le visiteur polymorphe"
Posté par Enzo Bricolo 🛠⚙🛠 . Évalué à 3.
Ca ferait un excellent titre pour un bouquin de SF !
Sinon concernant le lien j'aurai mis celui là) directement.
[^] # Re: "Le visiteur polymorphe"
Posté par rewind (Mastodon) . Évalué à 5.
Oui, je voulais mettre celui-là mais tu auras remarqué sur ton propre lien qu'il est faux à cause de la parenthèse finale. Et comme je ne me souvenais plus du code pour le mettre avec un % et qu'il était déjà très tard, j'ai fait au plus vite. Mais comme tout le monde arrive à tomber sur le bon lien assez vite, je me dis que j'ai bien fait de ne pas trop chercher. Et si un généreux admin peut le changer, ça sera nickel ;)
[^] # Re: "Le visiteur polymorphe"
Posté par JGO . Évalué à 2. Dernière modification le 25 avril 2013 à 14:59.
Tu sélectionnes l'URL telle qu'affichée dans Firefox, qui s'occupe de translittérer l'URL avant de la placer dans le buffer de copie (il n'a ce comportement que si tu sélectionnes l'URL en entier, pas si tu en sélectionnes juste quelques caractères).
[^] # Re: "Le visiteur polymorphe"
Posté par rewind (Mastodon) . Évalué à 3.
Du coup, ça marche moins bien avec Chromium ;)
# rtti lent
Posté par devnewton 🍺 (site web personnel) . Évalué à 1.
Quel compilateur utilises-tu? Je me souviens que l'implémentation de Microsoft était très lente, mais que d'autres s'en tirent mieux.
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
[^] # Re: rtti lent
Posté par Zarmakuizz (site web personnel) . Évalué à 5.
Le seul élément d'une chaîne de compilation dans ce journal est LLVM, donc il doit utiliser Clang.
Commentaire sous licence LPRAB - http://sam.zoy.org/lprab/
[^] # Re: rtti lent
Posté par Sylvestre Ledru (site web personnel) . Évalué à -2.
Non, pas nécessairement. LLVM est bien souvent compilé avec gcc.
[^] # Re: rtti lent
Posté par Gof (site web personnel) . Évalué à 6.
Un des problème de RTTI est que il grossi la taille du binaire,
RTTI rajoute plein d'informations pour toutes les classes (même celles pour lesquelles on a pas besoin de RTTI)
C'est pourquoi pas mal de projets compilent leur code avec -fno-rtti pour réduire la taille du binaire.
Ça veux dire pas de typeid, pas de dynamic_cast, pas d'exceptions.
[^] # Re: rtti lent
Posté par Troy McClure (site web personnel) . Évalué à 5.
Je me souviens que j'avais remarqué qu'en utilisant juste -fno-exceptions (donc en gardant le rtti) ça reduisait déjà la taille de mon appli (après strip) de ~15% !
[^] # Re: rtti lent
Posté par rewind (Mastodon) . Évalué à 3.
Petite correction, avec -fno-rtti, on a quand même droit aux exceptions. Il faut ajouter -fno-exception pour enlever complètement les exceptions. Dans LLVM, il n'y a ni exception, ni RTTI activé. Mais ils ont quand même leur propre système de RTTI à base d'enum, comme montré ici, qui leur permet de faire un genre de
dynamic_cast
.[^] # Re: rtti lent
Posté par rewind (Mastodon) . Évalué à 3.
J'ai essayé avec clang++ et g++ pour des résultats assez similaires. Ce qui ne m'étonne pas tant que ça vu que clang++ produit des binaires compatibles avec ceux de g++, donc utilise les mêmes structures pour type_info, et fait globalement la même chose.
# Compréhension
Posté par barmic . Évalué à 5.
Je ne comprends pas très bien l'intérêt de faire le dispatche à la main alors que le système de type du langage permet de le faire de manière fiable.
Le seul vrai avantage c'est le type de retour que l'on peut faire évoluer.
J'ai l'impression que c'est surtout « pour ceux qui n'aiment pas le polymorphisme » (et de ce que tu dis tu ne gagne pas en performance avec la version template même sans RTTI). Bref à mon avis il s'agit surtout d'avoir un code plus complexe (et donc moins maintenable/fiable) et plus lent, pour un gain limité (disons précis si tu préfère).
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Compréhension
Posté par devnewton 🍺 (site web personnel) . Évalué à 1.
Parce que C++ ne propose qu'un simple dispatch à base de méthodes virtuelles?
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
[^] # Re: Compréhension
Posté par barmic . Évalué à 6.
Donc l'intérêt c'est de pouvoir avoir des types de retour différents (ce qui est décris dans le journal et dont je parle dans mon commentaire), cool.
Mais en vrai ça sert si souvent que ça ?
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Compréhension
Posté par devnewton 🍺 (site web personnel) . Évalué à 0.
Il y a plusieurs usages, mais le plus courant c'est de pouvoir implémenter des traitements sur une hiérarchie d'objets hors de ces objets.
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
[^] # Re: Compréhension
Posté par barmic . Évalué à 4.
Ça c'est le visiteur. Pas besoin de l'implémenter en template pour ça.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Compréhension
Posté par Gof (site web personnel) . Évalué à 2.
Non, rien à voir. le type de retour dans ce cas là serait l'équivalent du type de retour de ta fonction virtuelle.
L'interrêt ici est plutot de séparé le code et les données.
Exemple fréquent dans un compilateur: tu as une classe de base (Statement) et des classe dérivée (IfStatement et ForStatement)
Ensuite tu veux écrire des passe d'optimisation, tu pourrais aoir quelque chose comme ça:
On voit deux problème:
1. la partie 'recurse' devra être répété dans toutes les passes d'optimisation.
2. Si je veux créé une nouvelle passe d'optimisation, je dois rajouter une fonction dans toute les classes. Alors que justement, les passes d'optimisations devraient être modulaire et contenue dans un seul fichier.
Le visiteur pattern permet de résoudre ces deux problèmes.
[^] # Re: Compréhension
Posté par barmic . Évalué à 4.
J'ai parlé de la version template. Le paterne en lui même je comprends tout à fais son intérêt.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Compréhension
Posté par Firwen (site web personnel) . Évalué à 4.
Pas uniquement en fait, ça permet aussi d’éviter l'ajout ( voir l'utilisation ) de méthodes virtuelles et les problèmes associés à celles-ci : ABI break, performance du à la vtable.
La deuxième raison d'utilisation de ce pattern est une raison de coupling entre l'algorithm ( le Visitor ) et l'objet lui même.
L'algo peut être instancié de manière différé, dérivé de manière autonome, ou encore avoir une association N <-> M avec l'objet en question.
[^] # Re: Compréhension
Posté par barmic . Évalué à 3.
Merci, là oui ça présente un intérêt (pas la version avec rtti).
Je n'ai vraiment pas du être clair, c'est la version template que je remet en cause pas le paterne.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Compréhension
Posté par rewind (Mastodon) . Évalué à 3.
Je ne dirais pas que ça complexifie le code. Avec un peu de préprocesseur, on parvient à générer un maximum de chose assez facilement. LLVM a d'ailleurs de ce point de vue des techniques assez intéressantes. Par exemple, dans le cas des instructions LLVM, ils ont un fichier dans lequel sont décrites toutes les instructions de manière assez simple. Et ils se servent de ce fichier pour générer plein de trucs dont le code de base du visiteur, que j'ai écris à la main ici mais dont on voit bien qu'il est assez répétitif. Ils le font pour plein de choses et c'est souvent fait de manière assez intelligente je trouve, et assez compréhensible.
Pour les cas complexes, ils ont un autre outil qui s'appelle TableGen.
# C++ 2011 ?
Posté par khivapia . Évalué à 2.
est-ce que les divers ajouts du C++ 2011 permettent de simplifier l'écriture et/ou d'améliorer l'efficacité des versions template ?
[^] # Re: C++ 2011 ?
Posté par Gof (site web personnel) . Évalué à 4.
Il utilise déjà C++11 (quand il écrit override)
D'ailleurs, question style: est-ce que rajouter 'virtual' en plus de 'override' n'est pas un peu redondant. Personnellement, je n'écris pas virtual quand j'override.
Je ne pense pas que le code template pourrait être simplifié. Peut-être que le typedef aurait pu être remplacé par sa nouvelle forme (prétendue plus cohérente)
[^] # Re: C++ 2011 ?
Posté par Anthony Jaguenaud . Évalué à 4.
Je viens de découvrir
override
, mais je ne voie pas bien l’intérêt par rapport àvirtual
.Si quelqu’un veut bien prendre le temps de m’instruire, je lui serai reconnaissant.
[^] # Re: C++ 2011 ?
Posté par Batchyx . Évalué à 4.
C'est la même chose qu'en Java: ça sert à détecter les surcharges involontaires. Par exemple
Ça compile parfaitement, mais
Derived::traiter_truc()
ne redéfinit pasBase::traiter_truc()
, et si on active pas les warnings qui vont bien dans son compilateur (qui sont chiants car parfois, c'est voulu), on s'en rend compte qu'à l'exécution… ou pas.Si
Derived::traiter_truc
était marqué en override, il y aurai une erreur de compilation.[^] # Re: C++ 2011 ?
Posté par sn00py . Évalué à 2.
Si tu fais une erreur dans ta déclaration (typo, par exemple), tu n'overrides pas une fonction de la classe de base et le compilateur génèrera une erreur. Avec virtual, tu auras simplement déclaré une nouvelle fonction virtuelle…
[^] # Re: C++ 2011 ?
Posté par Matthieu Moy (site web personnel) . Évalué à 2.
C'était d'ailleurs un truc particulièrement pénible en C++ : le moindre changement (genre un const en plus ou en moins) et c'est une nouvelle fonction, pas une redéfinition de celle de la classe de base. J'ai quelques mauvais souvenirs de debug de programmes pour lesquelles la mauvaise fonction était appelée à cause de ça, alors que le compilateur aurait pointé l'erreur immédiatement avec « override ».
[^] # Re: C++ 2011 ?
Posté par Batchyx . Évalué à 2.
Si tu utilise GCC ou Clang, compile avec
-Woverloaded-virtual
. Ça générera des warnings dans ce cas. Peut-être même un peu trop.[^] # Re: C++ 2011 ?
Posté par Gof (site web personnel) . Évalué à 6.
Très pratique aussi quand on fait du refactoring et que on renomme ou change les argument de helloWorld,
dans ce cas, on a des erreur de compile sur le code qui n'a pas encore été mis à jour (et c'est bien).
[^] # Re: C++ 2011 ?
Posté par Anthony Jaguenaud . Évalué à 3.
Merci à tous les trois (Batchyx, sn00py, Gof). Je ne voyais pas trop, et j’avais l’impression de faire un
virtual
différemment. En fait, c’est juste une information complémentaire pour le compilateur et éviter des erreurs bêtes.Encore merci, je peux poser le cerveau, j’ai appris un truc aujourd’hui ;-)
[^] # Re: C++ 2011 ?
Posté par rewind (Mastodon) . Évalué à 6. Dernière modification le 24 avril 2013 à 14:12.
Haaa :) Il y en a un qui l'a remarqué. Je l'ai pas mis pour faire du C++11 absolument mais pour voir si c'était pris en charge par la coloration C++. Et en fait, non.
Quant à savoir si C++11 permet d'améliorer les choses, je dirais non sur ce plan là effectivement.
Oui et non. Je sais que certains préconisent de ne pas mettre de
virtual
pour les réimplémentations de méthodes virtuelles, mais j'ai toujours trouvé ça très perturbant. Du coup, je l'ai toujours mis systématiquement. Maintenant, avec unoverride
, ça ne serait sans doute pas nécessaire mais ça n'apporte pas la même information je trouve. Et commeoverride
se situe en fin de ligne, c'est assez difficile d'avoir un aperçu de toutes les méthodes virtuelles. Tandis qu'avec unvirtual
systématique, on le voit mieux je trouve. Mais comme tu dis, c'est une question de style.# Cocasse
Posté par Thomas Sanchez . Évalué à 3.
Faire un article sur un design pattern dont on ne voit pas l'intérêt est déjà spécial (avec en plus pas d'exemple concret d'utilisation dans la vraie vie), mais en plus cette implémentation ressemble fortement a celle dans Modern C++ Design (qui pourrait être cité en référence aussi). Il me semble que celle de Modern C++ Design ne s’embête pas avec le type de retour.
Je suis cependant d'accord sur la conclusion.
[^] # Re: Cocasse
Posté par barmic . Évalué à 6.
Il n'a pas dis qu'il ne vois pas l'intérêt juste qu'il ne va pas en parler.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Cocasse
Posté par rewind (Mastodon) . Évalué à 3.
Tu as mal lu, j'ai mis un lien sur une utilisation dans LLVM (les compilateurs utilisent beaucoup ce design pattern).
Je n'ai jamais lu ce bouquin (je devrais peut-être) donc c'est assez difficile de le mettre en référence. Mais comme tu le cites ici, du coup, l'erreur est réparée ;)
# Dire que certaine pense que le Ocaml est illisible...
Posté par Nicolas Boulay (site web personnel) . Évalué à 10. Dernière modification le 24 avril 2013 à 10:56.
Quand on voit la complexité du truc…
Et encore, dans le match on peut mettre des bouts d'arbres comme :
| BASE (base_info, BASE (base_info2, []))
Le petit point difficile est l'usage d'une liste dans le type, mais on peut utilisé un type Option pour faire la terminaison de récursion.
Pour info :
(item :: list) permet d'ajouter un item au début d'une list ou de décomposer une liste dans les matchs.
(foo plop) permet d'appliquer la fonction foo au paramètre plop
En conclusion, vive les types sommes et le "pattern matching" d'arbre.
"La première sécurité est la liberté"
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par rewind (Mastodon) . Évalué à 1.
Pour le coup, je trouve qu'en essayant d'adapter au pied de biche un pattern objet à CaML, tu rends le CaML illisible. Je suis entièrement avec ta conclusion ceci-dit.
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par Nicolas Boulay (site web personnel) . Évalué à 5.
objet ou pas objet, le but est de pouvoir parcourir un arbre en séparant la définition de l'arbre et les parcours.
Et pour ça, les types sommes et le "pattern matching" sont totalement imbattables. C'est tellement puissant que je ne comprends pas pourquoi cela n'a pas été ajouter au C++.
C'est une très bonne alternative pour tous les cas ou il y a une pléthore de petit objet à gérer ensemble.
"La première sécurité est la liberté"
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par vlamy (site web personnel) . Évalué à 2.
Sur le même principe on a eut Scala dérivé de Java. C'est assez populaire mais la syntaxe en est quand même bien lourde, ce qui me fait sans hésiter retourner vers un langage fonctionnel dès que je le peux (Ocaml, Lisp ou Haskell).
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par Nicolas Boulay (site web personnel) . Évalué à 3.
Scala n'est pas du tout dérivé de java, il produit du code pour jvm, c'est tout. Et je suis d'accord que la syntaxe est encore pire que celle de Ocaml.
"La première sécurité est la liberté"
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par vlamy (site web personnel) . Évalué à 1. Dernière modification le 24 avril 2013 à 16:41.
Mince alors ! On m'aurait menti?
Wikipédia dit :
C'est comme ça qu'on me l'avait présenté et que je l'ai toujours vu. Je me coucherai moins bête ce soir. Merci pour la précision.
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par barmic . Évalué à 4.
Il est compatible c'est tout (comme groovy).
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par CrEv (site web personnel) . Évalué à 2.
Ce que tu cites ne dit absolument pas qu'il y a un lien d'héritage entre scala et java, ça doit venir d'une mauvaise compréhension de java/jvm.
Java est compilé en bytecode, qui s'exécute sur la jvm.
Scala est compilé en bytecode qui s'exécute sur la jvm.
C'est ce bytecode commun qui fait qu'il existe un pont, que tu peux utiliser des libs java en scala.
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par X345 . Évalué à -2.
Mouais… Enfin, Java et Scala sont quand même liés d'une certaine manière puisque Martin Odersky, qui est un des créateurs de Scala (si ce n'est leur chef de file), a énormément travaillé sur Java avant de créer Scala. Il fait notamment partie de ceux à l'origine de l'inclusion des generics dans Java et a bossé sur le compilateur Java.
De ce fait, il semble assez net que Java a largement influencé Scala. Alors certes, Scala n'est pas à proprement parler dérivé de Java dans le sens où il ne s'agit pas d'un superset de Java et que du code Java ne peut pas être compilé par le compilateur Scala mais l'histoire de Scala et Java sont quand même assez fortement liées.
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par barmic . Évalué à 2.
Et Java est inspiré de C++, lui même inspiré du C. Quasiment tous les langages ont des inspiration. Tu as même une partie spécialement pour ça sur Wikipedia. Ce n'est pas parce que Java est l'un des inspirateur de scala que la syntaxe de scala doit être proche de celle de Java (elle ne l'est pas en fait).
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par X345 . Évalué à 0.
On est totalement d'accord mais la question initiale était de dire si oui ou non on pouvait dire que Scala était un dérivé de Java, pas simplement de savoir s'ils avaient la même syntaxe ( "Sur le même principe on a eut Scala dérivé de Java" ).
En fonction de comment on interprète le mot "dérivé", on peut répondre oui ou non à cette question. Je dis ça parce que tout le monde a sauté sur l'aspect syntaxe/compilation alors qu'il me semble que ce n'est pas ce que voulait dire vlamy à l'origine. On retrouve certains des concepts de Java dans Scala (héritage simple et pas de possibilité de faire de l'héritage privé/protégé, type erasure, generics, fonctionnement sur une machine virtuelle …), en parallèle avec des concepts qui viennent d'ailleurs.
Après, je vais arrêter le troll là parce que ça devient du pinaillage, déjà que ma remarque initiale n'était pas mal en termes de pinaillage…
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par barmic . Évalué à 2.
La citation initiale complète :
J'ai présumé, comme d'autres, que les deux phrases, se suivant au sein d'un même paragraphe étaient liées.
Je ne ferrais pas de remarques sur les concepts aux quels tu fais références et qui ne sont pas liés à Java.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par X345 . Évalué à 3. Dernière modification le 25 avril 2013 à 00:43.
Jolie prétérition… Mis à part ça tout le monde sait que Java gère l'héritage multiple, que l'héritage privé est possible, que les annotations de type sont préservées à l'exécution et que la plupart des compilateurs Java produisent du code natif…
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par Nicolas Boulay (site web personnel) . Évalué à 1.
Scala est un langage fonctionnel, pas java…
"La première sécurité est la liberté"
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par freem . Évalué à 3.
Pas moi.
Je veux bien des sources d'ailleurs pour compléter ces lacunes?
S'il s'avère que c'est effectivement le cas, je risque de n'avoir plus que les unsigned à opposer :D (euhh… y'a pas encore, dis?)
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par windu.2b . Évalué à 7.
Java ne gère pas l'héritage multiple.
À partir de là, je te laisse conclure ce que tu veux du commentaire auquel tu réponds…
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par freem . Évalué à 1.
J'avais un doute sur le fait qu'il était ironique ou pas… me suis fait tromper par le coup du code natif, et il me semblait bien avoir lu il y a longtemps qu'il était possible de le faire (même si c'est… bref, c'était aussi y'a 6ans).
C'est le matin :)
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par claudex . Évalué à 2.
Hotspot compile le bytecode de la jvm en natif en JIT pour les fonctions souvent utilisées.
« Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par windu.2b . Évalué à 2.
La phrase exacte est :
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par barmic . Évalué à -1.
python est-il un dérivé de Java ?
scala fait de l'héritage dynamique, les traits et de l'inférence de type, rien que ça c'est extrêmement différent de ce que propose Java (ou même ce qui est dans les cartons pour Java8 ou plus loin encore).
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par vlamy (site web personnel) . Évalué à 2.
En fait je voulais parler de l'ensemble Java+Scala du coup. Ce qui serait équivalent à ajouter du fonctionnel dans C++ (pour revenir à la discussion de départ), plutôt que d'utiliser/développer un langage compatible mais indépendant (comme Scala du coup).
En gros : ma méconnaissance de Scala (que j'assimilais à Scala+Java) m'a fait pointé Scala comme un mauvais exemple, alors qu'à priori ce n'est pas le cas. Reste maintenant à voir ce que les gens font de Scala dans la vie de tous les jours, et je n'ai pas trop d'idée à ce sujet.
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par vlamy (site web personnel) . Évalué à 3.
J'avoue que j'ai lâché le mot « dérivé » un peu vite ! Mais l'esprit était là effectivement.
Je me rappelais juste que les gens de Scala avaient pour intention d'amener les dévs. Java au fonctionnel en facilitant la compatibilité entre les deux langages. Donc oui je persiste et je signe : il a existé un lien fort entre Java et Scala dès la sortie de ce dernier. Par contre, effectivement, parler de langage dérivé n'est pas approprié, d'où ma citation de Wikipédia qui me paraissait assez claire pour désambiguïser la chose.
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par vlamy (site web personnel) . Évalué à 3. Dernière modification le 25 avril 2013 à 09:46.
Ce n'est pas du tout ce que j'ai voulu laisser entendre. Je dis juste que quand on me l'a présenté (devrais-je préciser que c'était une présentation des auteurs du langage?) on a soutenu une volonté de compatibilité avec Java, qui aurait pour but d'amener en douceur les développeurs Java vers un langage fonctionnel (Scala donc). Ce qui ne veut pas dire effectivement que l'un est dérivé de l'autre, mais plutôt que Scala peut embarquer Java (ou l'inverse c'est à vous de voir).
C'est vrai que ce n'est pas évident de tout comprendre quand on appréhende Scala avec environnement Java+Scala. Ce qui était mon cas jusqu'à hier. C'est ce qui a motivé mon commentaire aussi.
En fait j'aurais dû mettre en exergue cette phrase :
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par X345 . Évalué à 1.
Je sens que je suis en train de nourrir le troll, mais…
Quels points spécifiques de la syntaxe Scala te font dire qu'elle est pire que celle de OCaml (je ne trouve pas la syntaxe de OCaml particulièrement horrible mais passons…) ?
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par max22 . Évalué à 1.
je vais peut-être dire une bêtise, mais est-ce qu'on ne pourrait pas utiliser un "fold" à la place du pattern matching ?
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par Nicolas Boulay (site web personnel) . Évalué à 3.
Sans doute, mais quand tu as 2 niveaux de fold, mon cerveau fait un overflow.
"La première sécurité est la liberté"
[^] # Re: Dire que certaine pense que le Ocaml est illisible...
Posté par neil . Évalué à 2. Dernière modification le 24 avril 2013 à 17:51.
Si c’est comme en Haskell, absolument. On peut définir le type considéré comme une instance de Foldable, et remplacer le code par un appel à un fold (voir, par exemple, sur Learn you a Haskell en fin de page).
# De la réinvention de la roue.
Posté par Batchyx . Évalué à 1.
Moi si on me disait aujourd'hui que je devais représenter une structure arborescente, et que je ne peux pas faire autrement (genre par exemple, j'ai vu des arborescences compliquées parcourues par des visiteurs, sauf que l'arborescence était statique…), je me poserait pas trop la question :
boost::variant
etboost::apply_visitor
. Si quelqu'un à une autre méthode où le visiteur peut gérer plusieurs types avec une méthode template, je prend.Après reste la question de comment l'utiliser: un
boost::variant<A,B,C...>
avec A, B, C contenant des pointeurs vers des variants, ouboost::variant<std::unique_ptr<A>, std::unique_ptr<B>, std::unique_ptr<C> >
. Chacun ayant ses inconvénients.Parce que bon, le coup de forcer ses types à être polymorphiques pour utiliser la RTTI ou de la réimplementer avec des énums, c'est un peu limite quand même.
[^] # Re: De la réinvention de la roue.
Posté par barmic . Évalué à 2.
Je pense que la question c'est plutôt comment s'est implémenté en boost.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: De la réinvention de la roue.
Posté par Batchyx . Évalué à 4.
Boost::Variant, c'est une « union »¹ et un entier pour dire quel type est actuellement utilisé, rien d'extrêmement compliqué. C'est comme la réimplémentation du RTTI avec un énum, sauf que c'est vérifié par le compilo, qu'il n'y a pas d'héritage et que ça permet d'utiliser des templates dans le visiteur. Et en plus, le code est déjà écrit (sinon au pire c'est pas bien compliqué à réimplémenter pour des cas spécifiques).
¹ Pas vraiment une union, car Boost::Variant supporte aussi les types avec des destructeurs et des constructeurs par copie qui lancent des exceptions, de manière assez poilue.
# Avantage pas compris
Posté par freem . Évalué à 1.
J'ai compris l'article, même si je suis assez septique sur les raisons d'utiliser la version template… mais un des commentaires plus haut à répondu avec un assez pertinent: ABI break restreinte (faudra que je réfléchisse un peu au comment du pourquoi, par contre, je n'ai pas encore pris le temps de penser en détail).
Par contre, il y a des "avantages" de la version template sur lesquels je suis vraiment dubitatif et ou j'aimerai une explication:
Justement, je trouve plutôt utile que le compilateur refuse de compiler quand le cas n'est pas pertinent, ça évite les bogues…
Je ne vois vraiment pas l'intérêt? Quand j'ai eu besoin de visiteur, c'était pour effectuer un traitement sur les données (sur un arbre dans mon cas passé). Je ne parviens pas à voir de situation ou je voudrais récupérer une donnée sur l'acte de visiter, sachant que le type de donnée en question va varier en fonction de l'objet visité… enfin, je m'embrouille, mais bref, j'aimerai un exemple concret de l'intérêt de ce point?
Pas vraiment un plus, puisque tu le dis toi-même, ça s'applique aussi à la version polymorphe?
Si je résume, on aurai la version template qui permet d'éviter d'avoir à utiliser la RTTI et de casser l'ABI, et la version polymorphe qui elle offre de meilleures performances?
[^] # Re: Avantage pas compris
Posté par rewind (Mastodon) . Évalué à 3.
Quand tu ajoutes une classe à ta hiérarchie, avec le visiteur polymorphe, tu dois déjà surcharger le accept. Bon, tu peux mettre un truc vide dans accept mais c'est un coup à l'oublier après (ça m'est déjà arrivé). Du coup, tu vas ajouter une méthode virtuelle au visiteur pour traiter cette nouvelle classe. Et il faudra ensuite ajouter toutes les surcharges dans tous les visiteurs. Enfin bref, tu te retrouves à devoir ajouter plein de code pour une simple petite classe.
Avec la version template, sans rien faire dans le accept et dans le visit, ça compile, et ça tombe dans le cas de base. Après, tu ajoutes le cas qui va bien dans le visit, et là, ça va même marcher pour quelques visiteurs pour lesquels tu auras regroupé les traitements pour une des classes mères. Donc dans ce cas, avec très peu de code, ça fonctionne plutôt pas mal.
Disons que tu veux afficher tes structures, là pas de souci, tu peux utiliser le visiteur qui renvoie void. Ensuite, tu veux calculer un truc sur tes structures, tu peux vouloir un visiteur qui renvoie directement le résultat du calcul plutôt que de passer par un membre. Exemple concret : tu veux calculer le type d'une expression binaire, tu vas définir un visiteur qui renvoie un truc de type Type que tu vas appliquer à des trucs de type Expression. Tu vas d'abord récupérer le Type de l'expression de gauche (à l'aide du même visiteur), puis le type de l'expression de droite puis, en fonction de l'opérateur, tu vas calculer le type de l'expression binaire et le renvoyer. Ne pas utiliser de type de retour va complexifier considérablement ton code.
C'est un plus dans le sens où ça se fait rarement sur les versions polymorphes (je n'ai jamais vu aucun exemple qui le faisait) mais que ça pourrait se faire.
En gros. C'est plus subtil, il y a aussi des considérations de style, de flexibilité, etc.
[^] # Re: Avantage pas compris
Posté par barmic . Évalué à 1.
Ajouter un attribut à ton visiteur avec un accesseur.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Avantage pas compris
Posté par rewind (Mastodon) . Évalué à 2.
Pas que. Comparons.
Version avec le type de retour.
Version sans le type de retour.
Ben je préfère la première version dans ce cas, beaucoup plus lisible et compréhensible.
[^] # Re: Avantage pas compris
Posté par freem . Évalué à 0.
Tu codes tassé toi dis donc, ça coûte si cher que ça les lignes vides? :D
Sinon, autre version, avec une méthode supplémentaire à implémenter:
Pour le coup, la lisibilité de visitBinaryExpression est la même, il n'y qu'une seule méthode supplémentaire a créer.
Note que je suis pas sûr de la bonne équivalence du code, vu que ton getResult() ne semble lié à aucun objet. J'ai donc supposé un prototype genre "Type* TypeDerive::getResult(void)" mais ça reste une supposition.
Si c'est lié à autre chose, le même principe peut se faire aussi de toute façon.
Je pense aussi que tu vas lever l'argument de la méthode virtuelle pure qui empêche d'utiliser accept() sur Type, mais ce n'est pas parce qu'une méthode est virtuelle pure qu'il est interdit de l'implémenter. C'est juste les filles ont l'obligation de le faire (j'ai appris ça il y a quelques mois, j'ai testé vite fait et effectivement… mais je n'ai pas trop joué avec, pas eu l'utilité encore).
PS: j'ai l'impression d'avoir merdé quelque part… alors je m'excuse par avance -.-'
[^] # Re: Avantage pas compris
Posté par barmic . Évalué à 2.
Je ne dis pas le contraire. C'est juste que je ne trouve pas que c'est considérablement plus complexe au vu de la différence de complexité entre l'implémentation polymorphe et template.
Là où ça deviens vraiment plus complexe c'est si tu souhaite paralléliser le calcul des sous résultats.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Avantage pas compris
Posté par rewind (Mastodon) . Évalué à 2.
Je ne trouve pas l'une tellement plus complexe que l'autre. La complexité ne se trouve pas au même endroit, c'est tout.
Alors là, pour le coup, ça ne change strictement rien, ça dépendra essentiellement de l'état interne de ton visiteur (est-ce qu'on peut appeler le visiteur en même temps sur la branche droite et la branche gauche, pour reprendre l'exemple) et pas de la manière dont tu as implémenté ton visiteur (template ou polymorphisme).
[^] # Re: Avantage pas compris
Posté par barmic . Évalué à 1.
J'ai lancé ça un peu comme ça. Mais tu peut avoir des méthodes sans effet de bords dans la version template, alors que dans la version polymorphe tu es obligé d'en avoir.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
# un inconvénient des templates
Posté par Yukito (site web personnel) . Évalué à 3.
Un inconvénient des templates, c'est la difficulté de compréhension du code. Sur une échelle de 1 à 10 en compétence C++, je me note à disons 8, et j'ai toujours autant de mal à comprendre les templates dès qu'ils sont un peu subtils comme ici. Autant dire que pour le commun des mortels, c'est juste du charabia imbuvable. Donc à éviter si possible.
Sinon, honnêtement, avant d'implémenter un visiteur, il faut commencer par se demander si on n'a pas un problème de design de l'architecture des classes. Et si on n'en a pas, attendre le lendemain matin, et se reposer la question une seconde fois…
[^] # Re: un inconvénient des templates
Posté par zul (site web personnel) . Évalué à 10.
C'est que tu te surnotes mon petit :). Le commun des développeurs C++ c'est plutôt vers 3 ou 4. Les templates ça n'a rien de difficile en soit, c'est juste que c'est une approche différente de l'approche 'OO avec classes' classiques.
Et franchement, ça (les visiteurs), c'est facile par rapport à des choses comme boost::proto, boost::spirit, nt2, et autres trucs vraiment poilus. Bref, soit les gens qui développent ça sont à 17 sur 10, soit ton échelle de valeur est cassé :).
[^] # Re: un inconvénient des templates
Posté par barmic . Évalué à 7.
Ou alors l'échelle n'est pas linéaire. :)
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: un inconvénient des templates
Posté par fearan . Évalué à 4. Dernière modification le 25 avril 2013 à 11:50.
Ouais enfin soit il est super pointu sur tout ce qui ne touche pas aux templates, pointeur de fonction, surcharge d'opérateur (dont les new, cast, delete)), soit il n'a pas encore croisé du code un petit peut corsé. Un petit exemple dans le code que j'ai sous la main ( l'un des plus simple):
Ce qui basiquement déplace à la fin du vecteur les élément vide ;)
Dans le code sur lequel je bosse j'ai aussi du bind2nd qui traine un poil et quelques utilisations plus poussé avec imbrication, me faisant me poser des question sur la santé mentale du gars qui a écrit le bordel, et parfois je me fait peur en voyant mon nom dans le annotate, et je me bénis (ou maudit) lorsque les commentaires expliquent (ou pas) l'intention du schmilbik.
Enfin tout ça, c'est l'usage c'est bien plus simple que l'écriture; fait toi peur en regardant les hpp de boost ;).
Ou alors son échelle à un putain de palier nécessitant du matériel d'escalade ;)
Il ne faut pas décorner les boeufs avant d'avoir semé le vent
[^] # Re: un inconvénient des templates
Posté par claudex . Évalué à 6.
J'ai modifié le commentaire pour faire apparaître le code qui était caché suite à une erreur lors de la déclaration du langage.
« Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche
[^] # Re: un inconvénient des templates
Posté par fearan . Évalué à 2.
Merci ;)
Il ne faut pas décorner les boeufs avant d'avoir semé le vent
[^] # Re: un inconvénient des templates
Posté par freem . Évalué à 4.
Je pense qu'on arrive au stade de la fusée la :)
[^] # Re: un inconvénient des templates
Posté par Batchyx . Évalué à 3.
Je vois pas ce qu'il y a d'illisible dans ton code. Ce n'est pas parce qu'on connais pas sa bibliothèque standard¹ que c'est forcément illisible.
Après si il y a ça sur trente lignes dans une seule fonction, son code est illisible, et il faut séparer ça en plusieurs fonctions. Tu ferais la même chose si tu voulais traduire ce code en C.
¹ Toutes les fonctionnalités de boost utilisées dans cette ligne sont dans C++11.
[^] # Re: un inconvénient des templates
Posté par Gof (site web personnel) . Évalué à 10.
Eugh ? qu'est-ce qu'il y a de subtile ? Ici on a affaire à tout ce qu'il y a de plus basic en matière de template. Pas de spécialisation partielle ou de lookup compliqués dans ces examples.
À la limite, le seul petit truc un peu curieux est l'utilisation du Curiously Recurring Template Pattern.
Bref, je ne te met pas 8/10 :-)
[^] # Re: un inconvénient des templates
Posté par fearan . Évalué à 4.
Si ça c'est subtil, regarde pas de trop près les boost::algorithm ou même std::algorithm, ni les std::mem_fun_ref et consort.
Sur les templates, coté difficulté celui là atteint péniblement 2 (les utilisations de base de vector ou string étant le niveau 1) (j'ai bien dit utilisation pas écriture ^ )
Il ne faut pas décorner les boeufs avant d'avoir semé le vent
[^] # Re: un inconvénient des templates
Posté par arnaudus . Évalué à 0.
Bah, autant dire que le C++ est imbittable, ce qui est probablement vrai. Ça fait quelques années que j'ai tendance à utiliser systématiquement des langages de haut niveau, et quand je vois des trucs comme ça, c'est clair que je n'ai aucune envie d'y retourner :-)
Mais bon, il y a plus imbittable que le code C++: les erreurs retournées par le compilateur, avec un petit bonus quand la STL est impliquée et qu'il faut scroller dans le terminal pour retrouver le début de la dernière erreur…
Après, imbittable ne veut pas dire inutile. En plus, la "bittabilité" est culturelle, le chinois est probablement aussi imbittable pour un européen que le français l'est pour un Chinois.
[^] # Re: un inconvénient des templates
Posté par rewind (Mastodon) . Évalué à 4.
Sauf qu'on aura toujours besoin de langage comme C/C++ pour implémenter des trucs qui doivent aller vite, comme les interpréteurs de langage haut niveau ou des compilateurs. Chacun son domaine.
Effectivement, tu n'as pas dû utiliser un compilateur C++ depuis bien longtemps et notamment clang parce qu'il y a eu de très très très gros progrès sur les messages d'erreur. clang a commencé et gcc est en train de s'y mettre.
[^] # Re: un inconvénient des templates
Posté par arnaudus . Évalué à 2.
C'est exactement ce que je disais à la fin de mon commentaire. Ceci dit, je pense qu'il reste une tendance à surutiliser le C++ dans des domaines où il n'est pas vraiment adapté—typiquement, clients "lourds" pour bureau, interfaces graphiques, etc. Une partie significative des petits jeux débiles livrés avec Gnome par exemple sont en C ou en C++, et je pense que c'est pareil sur toutes les plateformes.
[^] # Re: un inconvénient des templates
Posté par Nicolas Boulay (site web personnel) . Évalué à 3.
Sauf qu'on aura toujours besoin de langage comme C/C++ pour implémenter des trucs qui doivent aller vite, comme les interpréteurs de langage haut niveau ou des compilateurs. Chacun son domaine.
Ou que non alors ! Lisaac a déjà prouvé que l'on peut être du niveau de smaltalk en terme d'expressivité et battre le C++ en terme de vitesse.
OCaml est de trés haut niveau, mais les optimisations dans la génération de code sont minimes (pas de déroulage de boucle ou de spécialisation de fonction). Il est pourtant dans le top10 en terme de vitesse.
"La première sécurité est la liberté"
[^] # Re: un inconvénient des templates
Posté par freem . Évalué à 2.
Je n'arrive a rien trouver d'autre que les articles wikipedia sur lisaac… le site officiel n'affiche qu'une page avec sa propre URL en titre centré gris, le wiki à l'air HS, et les seuls trucs que je trouve à son sujet sont les endroits ou l'on peut utiliser son source… pas envie de fouiller dans du code source inconnu la :)
As-tu d'autres infos?
Pour OCaml… les seules choses que je lise sur wikipedia au sujet de sa vitesse, c'est que ça dépasse les 50% de la vitesse du C, et le passage ou il est dit que ses fonctions sont plus rapides que celles des langages impératifs contiens le mot théoriquement. Je sais qu'on ne peut pas forcément prouver (benchmark? Y'a toujours quelqu'un pour les renier…) qu'un langage est plus rapide qu'un autre, mais je me demande de quel top 10 tu parles?
En tout cas +1 pour avoir parlé de lisaac, il semble intéressant.
[^] # Re: un inconvénient des templates
Posté par Nicolas Boulay (site web personnel) . Évalué à 2.
Le dev de Lisaac est arreté. Le site est mort. Il y a eu un gros article sur les concepts manipulés publiés dans linux mag en début d'année dernière de mémoire.
http://www.ed-diamond.com/produit.php?ref=lmag148&id_rubrique=1
Comme benchmark :
http://benchmarksgame.alioth.debian.org/u32/code-used-time-used-shapes.php
Lisaac a été premier de ce benchmark quelque temps avant que les téchniques soient copié pour les code C et C++.
"La première sécurité est la liberté"
[^] # Re: un inconvénient des templates
Posté par zul (site web personnel) . Évalué à 2.
Un seul benchmark ne prouve pas grand chose. De plus, d'après la suite du commentaire, les différences ne viendraient pas forcément des optimisations permises par le langage mais l'algorithme utilisé (à moins que ce soit les optimisations qui étaient reprises dans g++). Haskell (enfin surtout ghc) arrive à battre le C (gcc) sur un ou deux benchmarks bien choisis, mais personne d'honnête n'irait prétendre que Haskell bat les performances de C.
À un moment, il faut être réaliste aussi. Ça fait des années qu'un "smart enough compiler" va arriver au niveau des performances du C. En pratique, ce n'est pas encore le cas (même si je crois personnellement que c'est possible). Pas la peine de vendre du rêve! Peut être que Rust va arriver à quelquechose de ce point de vue là.
[^] # Re: un inconvénient des templates
Posté par Nicolas Boulay (site web personnel) . Évalué à 2.
Il n'y a pas un seul benchmark, mais une dizaine. L'algo est fixe.
Haskell vu sa gestion de la mémoire à forcément des cas pathologiques.
Pas la peine de vendre du rêve!
Lisaac battait le code C dans la plus part de tests donc bon. Le problème n'est pas de faire un compilo intelligent. Le problème est de faire un langage avec suffisamment de sémantique pour qu'un compilateur puisse faire un boulot intelligent. Par exemple, le C fixe le layout mémoire de ces structures de données, et 2 pointeurs de même type sont censé pouvoir pointé sur la même zone mémoire. Ces 2 caractéristiques peuvent être des killers de performances. En gros, c'est le boulot du codeur, et le compilo ne peut rien faire.
"La première sécurité est la liberté"
[^] # Re: un inconvénient des templates
Posté par freem . Évalué à 2. Dernière modification le 25 avril 2013 à 16:06.
Battait, ça veut dire que C a rattrapé Lisaac ensuite?
Et sinon, le C++ n'a pas ces problèmes il me semble, et pourtant les bench disent souvent la même chose: il est souvent plus lent que le C.
[^] # Re: un inconvénient des templates
Posté par Nicolas Boulay (site web personnel) . Évalué à 1.
"Battait, ça veut dire que C a rattrapé Lisaac ensuite?"
Oui, car lisaac générant du C, c'est facile de comprendre pourquoi il est plus rapide. Au pire, tu copie/colle sa sortie et tu dis que c'est du C manuel.
"Et sinon, le C++ n'a pas ces problèmes il me semble, et pourtant les bench disent souvent la même chose: il est souvent plus lent que le C."
Dans le shootout, il est régulièrement premier grâce à openMP et les templates.
"La première sécurité est la liberté"
[^] # Re: un inconvénient des templates
Posté par freem . Évalué à 0. Dernière modification le 25 avril 2013 à 16:17.
Attends… t'es en train de dire qu'un langage générant du C était plus rapide que le C?
Tu cherches à me faire bugger par une boucle infinie ou quoi? XD
[^] # Re: un inconvénient des templates
Posté par Nicolas Boulay (site web personnel) . Évalué à 2.
Le C génére bien de l'assembleur.
Ces langages étant turing complet et bas niveau, on peut tous faire avec ou presque. Après, il y a une question de verbosité. Le code généré est plus gros, que ce tu ferais à la main, cela décale ton langage vers la gauche dans le graphe.
Donc, un langage générant du C peut être plus rapide et concis qu'un code C fait main.
"La première sécurité est la liberté"
[^] # Re: un inconvénient des templates
Posté par neil . Évalué à 1. Dernière modification le 25 avril 2013 à 23:29.
C’est quoi le problème de la gestion de la mémoire en Haskell ?
J’en voit plusieurs, mais ils ont tous des solutions, et c’est pour ça que j’utilise pas mal Haskell pour faire du calcul multi-dimensionnel sur des données volumineuses. Tu veux peut-être parler du fait que ce soit un langage de haut-niveau avec mémoire collectée, et que les paramètres du collecteur influencent les performances ? Ça tombe bien, il existe des outils graphiques pour analyser ça. Tu veux peut-être dire que l’évaluation paresseuse (en pensant thunks) peut remplir la pile ? Ça tombe bien, les bang patterns facilitent grandement l’écriture de code strict. Tu veux peut-être aussi parler du fait que tout les types sont par défaut boxés et donc prennent donc plus de place ? Ça tombe encore pas mal, vu qu’il existe pas mal de bibliothèques de type Array qui peuvent unboxer les types (e.g. repa, vector), et on peut aussi le faire directement à la main.
Évidemment, ça suppose de pas mal d’avoir un poil de connaissance sur le langage (Haskell restant un gros langage avec pas mal de concepts fonctionnels à connaître), ses extensions, son implémentation, et ses bibliothèques. Mais c’est pareil pour avoir des trucs optimisés en C. L’avantage est d’avoir un code relativement sûr, concis, avec pas mal d’optimisations faites par le compilateur en collaboration avec les bibliothèques (fusion de boucles, parallélisation automatique, utilisation des GPUs).
[^] # Re: un inconvénient des templates
Posté par Shuba . Évalué à 4.
Le truc qui me fait peur avec un langage qui gère automatiquement la mémoire c'est la tendance à créer des intermédiaires pour les calculs sans qu'on puisse l'empêcher. Et ça peut vraiment faire la différence en termes de performances, en tout cas c'est ce que j'observe entre faire du python/numpy et du C++.
Donc je me demandais si haskell permettait d'avoir le contrôle là dessus si désiré?
[^] # Re: un inconvénient des templates
Posté par Nicolas Boulay (site web personnel) . Évalué à 0.
Le problème est assez complexe, avec Ocaml tu peux facilement prédire les données que tu va créé. Haskell dispose d'optimisation dite de "deforestation" qui supprime les arbres de données intermédiaires, quand il le peut. Ocaml n'étant pas purement fonctionnel, j'imagine que la difficulté vient de là.
"La première sécurité est la liberté"
[^] # Re: un inconvénient des templates
Posté par neil . Évalué à 5.
Puisque tu parles de NumPy, j’imagine que tu veux parler du problème soulevé par son auteur. En clair, si tu écris une expression du genre
c = a**2 + exp(b)
aveca,b :: numpy.array
, l’interpréteur va d’abord créer un objet poura**2
, puis un pourexp(b)
et enfin sommer ces objets intermédiaires. Dans le même post sur son blog, l’auteur nous donne deux solutions qui se basent sur Cython ou Weave, en clair définir l’opération à effectuer dans un langage rapide et l’appeller depuis Python. On pourrait aussi rajouter la solution numexpr à la liste. Créer le code en C est effectivement la solution standard pour accélérer Python, en particulier pour réutiliser les bibliothèques existantes.Pour illustrer la version Haskell, on peut regarder comment fait la bibliothèque repa. En reprennant la même expression, repa ne va pas créer des tableaux entiers intermédiares, mais seulement un tableau retardé qui indique que pour avoir les éléments du résultat
exp(b)
(en syntax NumPy), il faudra appliquerexp
aux éléments deb
. En gros, un tableau retardé c’est une fonction. Quand tu vas combinera**2
exp(b)
, tu vas encore une fois créer une nouvelle fonction qui va dire comment trouver les éléments dec
(et qui en interne va utilisera
etb
). En gros le vrai tableau n’est généré (de façon parallèle !) qu’au moment où tu en as besoin (en le forçant), en utilisant différentes astuces pour avoir un code (par exemple, si tu faisf(exp(b))
, il va automatiquement combinerf
etexp
pour avoir un code optimal). Ça marche aussi de façon unifiée pour les changements de coordonnées (ça NumPy le fait un peu).[^] # Re: un inconvénient des templates
Posté par Shuba . Évalué à 3.
Ah c'est très intéressant cette approche paresseuse en effet.
[^] # Re: un inconvénient des templates
Posté par neil . Évalué à 2.
Pour avoir juste l’évaluation paresseuse en NumPy, il y a lazyarray.
[^] # Re: un inconvénient des templates
Posté par Nicolas Boulay (site web personnel) . Évalué à 1.
Je pensais plus au fait qu'il était trés difficile de déterminer la taille des données mémoires. Certain industriel avait laisser tomber Haskell car de petites modifications pouvait faire exploser son usage de la mémoire. C'était un des arguments d'OCaml ou sa gestion des objets mémoire est très prévisible.
"La première sécurité est la liberté"
[^] # Re: un inconvénient des templates
Posté par fearan . Évalué à 5.
Ça me fait penser qu'on m'avais vanté la vitesse de java sur le C avec code à l'appui. J'ai vite regardé le code, parcours à l'envers d'un tableau, pas d'option de compil genre -O3 ou -O2, bref du beau n'importe quoi.
Il ne faut pas décorner les boeufs avant d'avoir semé le vent
[^] # Re: un inconvénient des templates
Posté par Nicolas Boulay (site web personnel) . Évalué à 1.
J'ai écrit et optimier une IA en java. La vitesse est digne d'un gcc -O0, pas d'inline des getter/setter, etc… Cela ne peut pas être rapide, même les "clause if" n'étaient pas sorti des boucles.
"La première sécurité est la liberté"
[^] # Re: un inconvénient des templates
Posté par freem . Évalué à 1.
J'ai aussi vu ce bench, je crois :)
C'était un moment d'anthologie pour moi qui aime rire.
[^] # Re: un inconvénient des templates
Posté par freem . Évalué à 1.
C'est marrant de dire qu'un langage mort est capable de faire mieux que les existants… pourtant, il y a pas mal de langages de niche (dans la catégorie merdique, j'appelle PowerBuilder!), donc je suis intrigué qu'il n'ait pas réussi s'il est meilleur (bien que ce soit très possible, je ne le nie pas).
Ce benchmark est à 2 dimensions: taille du code (et pas expressivité) à l'horizontale et vitesse d'exécution sur la hauteur, si je ne me trompe pas?
Pour le coup (prêcher pour ma paroisse avec force mauvaise foi - comme ça c'est dit ;) - ne m'a jamais empêché de dormir) je remarque que comparer ocaml au C++ est intéressant en effet j'ai regardé sur du quad-core (C++ et les thread c'était pas ça, jusqu'au C++ après tout… toujours pas testé d'ailleurs) et je remarque qu'Ocaml est plus économe en mémoire. Sur 3 domaines. Equivalent sur 2, et il perds sur 5.
Niveau vitesse, il atteint C++ sur 2 domaines, les autres C++ gagne.
Code plus petit (de moitié) dans 1 cas, plus grand dans 2 cas, et équivalent dans les autres.
Pour le coup, je te remercie, ce bench est très intéressant, même si je m'en suis un peu servi pour embêter le monde mesquinement :)
Notes un peu plus objectives et de moins mauvaise foi:
[^] # Re: un inconvénient des templates
Posté par Nicolas Boulay (site web personnel) . Évalué à 2. Dernière modification le 25 avril 2013 à 16:11.
"je suis intrigué qu'il n'ait pas réussi s'il est meilleur"
Le code du compilo n'était pas simple du tout (détermination du type réel de chaque objet). Et le dev principal a coupé les ponts du jour au lendemain.
Les codes c++ et C utilisent massivement openMP qui n'existe pas dans le monde ocaml.
"Ce benchmark est à 2 dimensions: taille du code (et pas expressivité) à l'horizontale et vitesse d'exécution sur la hauteur, si je ne me trompe pas?"
Non, c'est juste l'affichage de ce graph, il est intéressant car la case la plus intéressante est en bas à droite : compact et rapide.
"ils mesurent la taille du code en octets, en ayant enlevé commentaires et espaces, et en compressant le texte ainsi obtenu. Franchement… je trouve difficile de trouver une façon moins pertinente de mesurer la taille des codes."
Au contraire, cela évite de parler de la définition de la "ligne de code". La compression limite l'augmentation de taille des langage verbeux par rapport à ceux abusant des symboles.
"il n'y a que des algo de calcul, donc pas d'accès aux ressources, de gestion d'IHM, et caetera. Donc, comme d'hab avec les bench, résultats à n'utiliser que pour des optimisations des "zones de calcul"."
C'est vrai. Mais les problèmes de logiciels dans ce domaine, sont liés aux algos utilisés. Il faut aussi que la taille du benchmark reste accessible aux codeurs. Il y a aussi des benchs manipulant des symboles (de mémoire, le truc qui manipule de l'ADN).
"La première sécurité est la liberté"
[^] # Re: un inconvénient des templates
Posté par freem . Évalué à -1.
Je connais assez mal openMP, mais qu'est-ce qui empêche OCaml de l'utiliser? Pas moyen d'utiliser une API C dans OCaml? Mais alors, comment faire pour utiliser l'API de l'OS sous-jacent?
Désolé, mais je trouve cet argument plutôt contre que pour OCaml. Même Java et C# savent exploiter une API C… Ce serait dû au fait de ne pas être impératif?
Les langages les plus rapides et concis sont en bas à gauche, non? J'ai toujours du mal avec droite et gauche en anglais…
Argument intéressant.
Mais je voulais surtout dire que je ne considère pas la taille d'un code comme un indice par rapport au fait qu'il soit lisible: perl produit des codes pouvant parser des documents complexes en peu de lignes, mais il est tout bonnement horrible à lire… A contrario, java est très simple à lire, mais j'ai l'impression qu'il se transforme souvent en romans à l'eau de rose, et mieux vaut avoir 2 écrans larges pour coder confortablement.
De quel domaine parles-tu? Dans la discussion, on parlait de façon assez générale il me semble… cette série de bench est intéressante, je suis d'accord, je rappelais juste (pour la même raison que je parlais de mauvaise foi en défendant le C++ sur tous les points) que les bench sont toujours là pour montrer l'efficacité dans un domaine précis.
Ici, ça semble être le calcul scientifique?
[^] # Re: un inconvénient des templates
Posté par Nicolas Boulay (site web personnel) . Évalué à 3.
openMP n'est pas une api C. Ce sont des directives de compilation pour générer du code multithread.
"la taille d'un code comme un indice par rapport au fait qu'il soit lisible"
Non, mais sur sa concision. Il y a eu des études portant sur la productivité (cocomo) quelque soit le langage, la productivité en ligne de code par unité de temps est la même.
"De quel domaine parles-tu? Dans la discussion, on parlait de façon assez générale il me semble…"
Je pensais à l'IHM.
"Ici, ça semble être le calcul scientifique?"
Non, il y a aussi manipulation de symbole.
"La première sécurité est la liberté"
[^] # Re: un inconvénient des templates
Posté par freem . Évalué à 1.
Et on peut pas faire la même chose avec OCaml? (pour la confusion: l'encart rapide sur wikipedia UK dit "Written in C, C++, Fortran" et "Type API" mais je te crois sur parole: n'ayant jamais utilisé et ayant déjà relevé des erreurs ou imprécisions sur wikipedia, je préfère faire confiance à quelqu'un tant que ses propos sont pas aberrants :) )
J'ai entendu parle de cocomo… quand j'ai parlé du problème du sucre syntaxique plus important des langages objet genre C++ (public/protected/private sur une ligne propre, accolades souvent seuls sur leurs lignes, déclarations/définitions dans des fichiers distincts -donc 2 lignes de code par prototype-, …) il m'a répondu que c'était plutôt utilisé par les commerciaux et a clairement remis en cause l'intérêt. J'ai gardé le nom dans un coin de mémoire morte mais sans creuser plus du coups.
Si tu as des ressources intéressantes à ce sujet je suis preneur, si tu estimes que ça permets vraiment d'estimer les coûts d'un projet en fonction des langages utilisés.
[^] # Re: un inconvénient des templates
Posté par Nicolas Boulay (site web personnel) . Évalué à 3.
Cela va te lancer n thread en découpant la clause for en morceau. Le système se débrouille même si tu peux aussi le guider. Sur du code numérique, c'est assez facile du moment que tu comprends que tu ne peux pas partager d'information entre threads.
Si tu as des ressources intéressantes à ce sujet je suis preneur, si tu estimes que ça permets vraiment d'estimer les coûts d'un projet en fonction des langages utilisés.
https://en.wikipedia.org/wiki/COCOMO ?
Je retient surtout : ab*(KLOC)bb. Cela veut dire que la difficulté n'est pas linéaire au nombre de ligne, mais augmente plus vite.
"La première sécurité est la liberté"
[^] # Commentaire supprimé
Posté par Anonyme . Évalué à 4.
Ce commentaire a été supprimé par l’équipe de modération.
[^] # Re: un inconvénient des templates
Posté par Nicolas Boulay (site web personnel) . Évalué à 3.
cocomo ne mesure pas la difficulté de changement, mais le temps global pour écrire le code. Le problème est que le nombre exacte de kloc est connu à la fin du projet.
Et si le cout est 100x, c'est parce qu'au début, cela prend 5min pour changer une spec, alors qu'à la fin, c'est le client qui trouve l'erreur, la remonte au support, qui transmet à la validation pour confirmation, qui remonte ensuite au dev.
"La première sécurité est la liberté"
[^] # Re: un inconvénient des templates
Posté par chimrod (site web personnel) . Évalué à 2.
Ocaml est plombé par la gestion des threads. Il n'est pas possible de faire de code multithreadé en ocaml, à cause du garbage collector.
Des tentatives pour compiler une version compatible ont été tentées (oc4mc), mais n'ont jamais été intégrées dans la branche principale, et ne le seront jamais (des messages sur la ml que je ne retrouve plus en écrivant ce post disent en gros que des solutions pour faire du calcul distribué existent et fonctionnent bien, gérer plusieurs processus nativement n'est donc pas à l'ordre du jour).
C'est un peu le problème qu'avait rencontré python il y a quelques années, mais avait réussi à s'en sortir.
En dehors de ça, j'ai l'impression que le langage Ocaml recommence à faire parler de lui, après quelques années en sommeil. Un regain pour le fonctionnel ?
[^] # Re: un inconvénient des templates
Posté par Nicolas Boulay (site web personnel) . Évalué à 1.
Disons que faire du pthread propre est une vrai horreur. Le vrai multi-process est revenu à l'honneur avec chrome. Il "suffit" d'ajouter une lib de passage de message propre et rapide.
Mais c'est vrai aussi que des traitements parallèle de data pourrait être sympa (map fold/reduce en multicpu).
"En dehors de ça, j'ai l'impression que le langage Ocaml recommence à faire parler de lui, après quelques années en sommeil. Un regain pour le fonctionnel ?"
Peut être est-ce la création de Ocaml pro ? Ou la pub sur l'usage qu'en font quelques boite comme janes street (vive le HFT en Ocaml).
"La première sécurité est la liberté"
[^] # Re: un inconvénient des templates
Posté par chimrod (site web personnel) . Évalué à 2.
Il y a parmap qui fait ça (mais avec des bindings C, on n'est plus dans Ocaml pur).
En fait, j'ai l'impression que le langage commence à monter son propre environnement : Gestionnaire de paquets, librairies avancées, ce qui manquait pour sortir d'un simple langage théorique. Il reste encore beaucoup à faire (compiler sous windows reste encore une épreuve), mais ça commence à bouger. Je ne connais pas assez Ocaml pro pour savoir s'ils accompagnent le mouvement ou s'ils donnent une nouvelle dynamique.
[^] # Re: un inconvénient des templates
Posté par Nicolas Boulay (site web personnel) . Évalué à 1.
Disons que le dev d'ocaml était purement universitaire, ils étaient plus intéressé dans le développement des derniers concepts avancés de typage (le dernier type à l'air super puissant, mais je n'ai toujours pas compris son fonctionnement) que dans le fait d'avoir des messages d'erreurs précis et compréhensible, ou un module Eclipse fonctionnel. Ocaml pro veut changer cela, on dirait.
"La première sécurité est la liberté"
[^] # Re: un inconvénient des templates
Posté par Michaël (site web personnel) . Évalué à 5.
Au contraire, la taille du fichier compressé est une bonne approximation de la quantité d'information qu'il contient.
[^] # Re: un inconvénient des templates
Posté par Gof (site web personnel) . Évalué à 2.
Il faut utiliser un compilateur récent qui donne des erreurs correcte. Comme clang. Même GCC 4.8 a fait beaucoup de progrès à ce niveau.
Et puis les bons IDE te présentent les erreurs correctement.
[^] # Re: un inconvénient des templates
Posté par freem . Évalué à 4.
Allez, j'ai envie de tomber dans ton troll:
Ca tombe bien, C++ est un langage de haut niveau. Il est aussi bas niveau, cependant. Donc moyen niveau selon wikipedia, parce qu'il intègre des éléments des 2.
Note quand même que, perso, je me passe très bien de l'allocation mémoire, y compris pour les collections polymorphes, grâces à boost::ptr_container.
C++
Le truc que tu vois qui ne te donne pas envie, ça s'appelle le paradigme de la programmation générique et selon wikipedia, "C'est un concept important pour un langage de haut niveau car il permet d'augmenter le niveau d'abstraction du langage."
Faut pas confondre langage de haut niveau et langage simpliste :D
Enfin un peu de vérité… un poil obsolète, mais malgré tout encore d'actualité. Essaies clang.
Pour clôturer ce message, le problème du C++ c'est pas le langage lui-même, mais la pauvreté de sa lib standard, qui a grandement été fixé par C++11 et devrait être encore largement amélioré dans 2-3 ans. En attendant, y'a boost.
Et pour les IHM, t'as le choix: MFC, Qt, GTK, WxWidgets…
# C++ et les templates de haut vol
Posté par Fabimaru (site web personnel) . Évalué à 3.
Comme dit Nicolas Boulay, ça demande de la réflexion pour comprendre. Ce qui me rend perplexe, c'est quand on pose le bouchon plus loin pour faire des trucs tordus du style méta-programming qu'on trouve dans boost. Pour moi, c'est tellement complexe que ça en devient une boîte noire. Un truc avec une syntaxe proche du c++, mais qui crachera des messages d'erreur incompréhensibles en cas de typo.
Et quand c'est compliqué, trop éloigné de l'usage de base du langage, ça devient difficile de faire du support, surtout si il s'agit du code d'un autre (par exemple un collègue parti pour d'autres horizons).
[^] # Re: C++ et les templates de haut vol
Posté par devnewton 🍺 (site web personnel) . Évalué à 6.
Une fois habitué au style "boost", ce n'est pas si difficile, mais par contre les temps de compilation tendent vers l'infini et au delà.
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
[^] # Re: C++ et les templates de haut vol
Posté par freem . Évalué à 4.
C++11 à justement intégré des outils qui permettent de simplifier les messages d'erreur: les assertions statiques
Sinon, je ne crois pas que le C++ ait un jour été destiné à être un langage de programmation pour débutant.
Pas plus que les design pattern ne doivent être employés sans réflexion (surtout pas même, ça te pourris un code très vite sinon), donc la réflexion qu'engage cet article me semble plutôt salutaire.
De là à qualifier les sources affichées de "template de haut vol" par contre, il y a un gouffre que je n'oserais pas franchir. Si toi oui, alors ne lis jamais le source de la STL fournie avec Gnu… (ça m'arrive régulièrement, mais je suis toujours largué quand je le fais)
# Intérêt du visiteur ?
Posté par Anthony Jaguenaud . Évalué à 3.
Salut,
En ayant lu l’ensemble, je me demande toujours ce qu’est concrètement un visiteur ?
J’ai l’impression que ça sert à implémenter une sorte de « model-view » ?
Quelqu’un aurait-il la gentillesse de faire un exemple réel du design-patern ? Car en dehors du bonheur d’apprendre du c++, je veux bien apprendre aussi des design-patern…
[^] # Re: Intérêt du visiteur ?
Posté par Michaël (site web personnel) . Évalué à 5.
Par exemple Base est abstraite pure et représente les expressions algébriques,les classes dérivées concrètes représentent les atomes (nombres et indeterminées) et les combinateurs + et * (pour simplifier).
Tu peux alors implémenter les algorithmes développer, dériver ou évaluer comme des visiteurs concrets de la classe de base.
Le point clef du modèle est que tu veux implémenter un traitement par une classe (le visiteur) qui reçoit un pointeur sur une classe abstraite, surlaquelle le visiteur ne sait rien faire: les traitements ne sont définis que sur les classes concrètes. En renversant l'ordre d'appel (c'est la classe abstraite qui se présente au visiteur par une méthode virtuelle, ce qui permet de récupérer le type concret de la classe).
# Polymorphisme
Posté par Michaël (site web personnel) . Évalué à 5. Dernière modification le 25 avril 2013 à 01:12.
En C++ il y a deux mécanismes de polymorphisme: les méthodes virtuelles où la résolution se passe à l'éxécution du programme, et les templates, où la résolution se passe à la compilation.
Du coup quand on lit un truc du style «Le Visiteur template à base de RTTI» qui annonce mélanger du polymorphisme à l'éxécution et du polymorphisme à la compilation, on se dit à quoi bon?
Si tu ne veux pas montrer ton membre dans l'espace public, il suffit d'encapsuler l'appel à Visitor::visit dans une fonction qui renvoie la valeur du membre. Au passage, cela permet de donner un vrai nom à la fonction au lieu de visit.
L'implémentation classique du modèle n'est d'ailleurs pas ce que tu donnes: dans Base la méthode accept est virtuelle et abstraite et implémentée dans les classes concrètes Derived1, Derived2. Dans ce cas Visitor::visit(Base& b) est b.accept(*this).
[^] # Re: Polymorphisme
Posté par rewind (Mastodon) . Évalué à 3.
visit
n'est jamais appelé directement de l'extérieur (il l'est uniquement dans les fonctionsaccept
), c'est bienaccept
qui est appelé mais soit, on peut reprendre ton argument et l'adapter àaccept
. C'est juste une question de style et de simplicité et de choix.Alors ça, ça dépend de ce qu'est
Base
et de ce qu'estDerived1
etDerived2
. Et si on applique le petit plus que j'évoque (appeler le visiteur de la classe mère), tu auras unaccept
pour Base.[^] # Re: Polymorphisme
Posté par barmic . Évalué à 10.
C'est surtout que tu va au devant de problème avec la police.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Polymorphisme
Posté par Michaël (site web personnel) . Évalué à 5.
Ça fait plaisir de voir qu'il y en a qui suivent! :-)
# Jour... Nuit...
Posté par 2PetitsVerres . Évalué à -3.
Okay !
Tous les nombres premiers sont impairs, sauf un. Tous les nombres premiers sont impairs, sauf deux.
[^] # Re: Jour... Nuit...
Posté par max22 . Évalué à -1.
j'ai mis un peu de temps à comprendre…
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.