C'est simplement que ce n'est pas la même technique, chacun apportant une réponse à des cas particuliers, en particulier ce qui justifie l'utilisation des templates c'est que dès la compilation, on sait quelles méthodes vont être appelées. Si on reprend l'algorithme de tri, avec des interfaces on a vu qu'on utilisait un une classe héritant de Comparator qui est une interface, si je veux implémenter mon propre comparator, je ferai :
class MonComparator : public Comparator
{
int compare(Object o1, Object o2)
{
/* le code qui fait la comparaison */
}
};
Pour trier on va alors instancier un objet MonComparator et le passer à la fonction Collection.sort().
Avec les templates, l'algorithme std::sort prend en paramètre une fonction, non pas un pointeur de fonction comme c'est le cas en C avec la fonction qsort mais un nom de fonction, le compilateur étant en charge de générer le code avec la bonne fonction. la declaration de std::sort ressemble à ça :
A la compilation, on déclare une nouvelle fonction sort qui prend en troisième paramètre une classe de type MonComparateur.
Les différence entre les deux approches :
- La principale c'est que l'approche template implémente une nouvelle fonction std::sort pour chaque types de paramètres différents, si je réutilise ma fonction std::sort() avec un autre comparateur (std::less par exemple), j'aurai une deuxième fonction sort prenant des paramêtres différents.
- Avec les templates, mon comparateur compare directement le type qu'il souhaite et n'a pas besoin de "caster" les Object vers le type souhaiter, on a donc une erreur dès la compilation en cas d'utilisation d'un comparateur sur un mauvais type (ceci n'est plus vrai il me semble en Java5 et en .Net2, l'interface Comparator étant une interface generique qui prend en paramètre le type comparé).
C'est vraiment important de saisir qu'avec les template, à chaque appel à une fonction avec des paramêtre différent, le compilateur crée un nouvelle fonction qui s'appel de la même façon que si elle était apellée directement.
C'est un exemple volontairement simple qui ne couvre pas tout ce qu'on peut faire ni avec l'héritage, ni avec les templates mais qui, je l'espère, permet de saisir la différence technique.
Je connais très peu java, l'impression que j'en ai est que la seule différence c'est qu'en Java, l'opérateur de comparaison doit faire des casts vers l'objet à comparer là où le C++, resolvant le type à la compilation ne le fait pas (par extension, le C++ n'a pas besoin non plus besoin que la classe à trier hérite de la class List mais qu'à la compilation on trouve les fonctions dont l'algorithme à besoin). Sinon il semble bien que ce soit identique.
Si c'est pour le constructeur de fstream, c'est vrai, j'aurai du dire : on ne manipule pas de char*, d'ailleurs, les seuls moments où on a recours au pointeur de char, c'est des "const char*", donc pas pour les manipuler.
J'avoue que j'ignore ce qui justifie qu'on n'ai qu'un constructeur prenant un "const char*".
Oui c'est de l'impératif car dans cette situation c'est la meilleurs choses et ça te permet de trier n'importe quel container sur n'importe quel type auquel tu peux fournir une fonction de comparaison.
Ce n'est pas une limite du modèle objet c'est un choix de ne pas l'utiliser dans certains cas.
Si on n'avait pas de template aussi puissant en C++, nul doute que la librairie standard aurait ressemblé d'avantage à QtCore, mais il se trouve que, en plus du modèle objet, on dispose de mechanismes particulièrement puissants qui ont été utilisés.
C++/stl a fait des choix, et ils privilégient les templates plutôt que l'héritage (en partie je pense parce que les interfaces n'existent pas en tant que telles)
C'est faux, la généricité n'est pas du tout la même avec des interfaces et des templates.
Ca en fait un modèle un peu bancal, un coup on a un objet, un coup on a un template, ...
C'est un langage multi-paradigme et on utilise celui qui correspond le mieux à l'endroit où on en a besoin. D'ailleurs la STL ce n'est pas un coup un objet un coup un template c'est des templates partout.
Ta critique revient à dire que, par exemple, on ne devrait pas mélanger le multithreading et le multiprocess, mais chaque chose a son avantage dans différentes situations et pour des problématiques différentes.
Et honnêtement, trier des chaînes, je le fais moins souvent que les découper en fonction d'un token.
Je suis pas là pour faire un cours de C++ mais ce que tu me dis là se résout par exemple en utilisant un std::stringstream pour voir ta chaine de charactère comme un flux puis utiliser std::getline en lui fournissant ton token. Pour assembler par exemple un vecteur de strings en une seule string séparée par un token, tu vas utiliser std::copy avec un std::ostream_iterator. Il est vrai que ça demande d'être familier avec les différents composants fournis par la STL pour pouvoir jongler avec et que c'est plus long à apprendre que QtCore par exemple.
La STL n'a pas vocation à prévoir tous les usages. Si je prend l'exemple de Qt, la classe QString me fournie les fonctions toUtf8(), toAscii() et quelques autres, bien sûr elle ne founit pas sous forme de fonctions membre tous les encodages possible. Avec la STL, il faudra passer par un std::copy() par exemple et fournir un functor qui convertis d'un encodage à un autre, mais tout est fait pour être générique.
Je comprend qu'on ne soit pas familier avec ce genre de chose et qu'on préfère avoir des fonctions membres pour tous les usages mais ce n'est pas la philosophie de la STL. En même temps libre à chacun de ne pas l'utiliser mais c'est souvent plus à cause de la trop grande généricité qu'à cause d'une vrai impossibilité.
On n'a pas une fonction sort qui prend un container, on a une fonction sort qui prend 2 itérateurs et une fonction de comparaison (std::less par défaut). C'est le principe de la stl de travailler sur des containers et je conçois qu'on puisse trouver ça discutable et pas intuitif mais c'est aussi beaucoup plus puissant.
Je ne vois pas trop ce que tu entend par "modèle objet dans c++", la STL est ce qu'elle est pour privilégier les souplesse et les performances, la STL utilise de façon très intensive les templates plutôt que l'héritage et les fonctions virtuelles pour gérer la généricité car, la résolution se faisant à la compilation, c'est beaucoup plus rapide.
Pour prendre un exemple, pour tous les containers on peut fournir son propre allocateur de mémoire. Pour "faire plus objet", on aurait pus avoir à fournir au constructeur une instance d'une classe héritant de IAllocator, ce qui aurait induit un appel à une fonction virtuelle pour chaque allocation. Le choix qui a été fait est de fournir une classe en paramètre template, ce qui permet de déterminer l'appel de fonction dès la compilation.
Le C++ permet d'utiliser plusieurs paradigmes pour la généricité, la STL a fait le choix d'utiliser les templates ça ne veut pas dire qu'on ne peux pas utiliser autre chose et qu'on ne peux pas coder de façon plus "orienté objet" en C++.
Le concept de la stl est de separer les containers et les fonctions de manipulations. Donc la classe std::string ne contient pas énormément de fonctions, il faut regarder du côtés de fonctions et fonctors de la stl.
Par exemple si je veux trier une std::list, un std::vector ou un autre container sequentiel, je ferais de la même façon
std::sort(container.begin(), container.end());
Comme ceci, je peux utiliser le container qui est le plus adapté (fournit par la stl ou un autre). C'est sans doute cela qui est déroutant quand on n'est pas habitué.
Le reproche que je fais à la stl c'est de n'être pas assez complète, ceci étant dû à la façon de faire évoluer le standard au sein du commité. C'est pour celà qu'on a très souvent recours à un bibliothèque comme boost (dont certains éléments passe dans le standard comme les shared_ptr).
D'ailleurs, les std::* ne sont pas à proprement parlé du C++ mais simplement une bibliothèque écrite en c++.
Une implémentation de C++ qui ne fournit pas de std::string n'est pas du C++, car la STL est justement décrite dans le standard du C++.
Le langage est composé d'une syntaxe et d'une bibliothèque standard.
Pour prendre ton exemple des MFC, c'est exactement l'exemple où on fait non pas du C++ mais du "C with classes" et ça n'utilise de C++ que les classes (on aurait pû faire aussi dégueulasse en Objective-C soit dit en passant).
Qu'on puisse ne pas utiliser la bibliothèque standard est vrai dans tous les langages. Mais va faire un tour sur les newsgroups (fr.)?comp.lang.c++ ou lis les livres de Bjarne Stroustrup, Herb Sutter ou Andreï Alexandrescu pour voir que le C++ est loin d'être une "simple surcouche au C" et qu'on ne programme pas du tout de la même façon en C et C++.
En un mot: C++ est une couche très épaisse au dessus du C. Objective-C est une couche très fine au dessus du C.
Je pense que justement le C++ n'est pas une couche au dessus du C, contrairement à Objective-C. C'est un autre langage qui s'interface très facilement avec le C mais c'est plus à voir comme un autre langage. Pour illustrer mon propos, en C++, on n'utilise pas (en tout cas c'est plus que déconseillé) de chaine de charactères en char* mais des std::string, de même qu'on utilise pas de pointeurs pour faire des tableaux mais des std::vector<> (ou std::array encore en tr1). Il y a très peu de choses que l'on fait en C++ de la même manière qu'on le fait en C. Certe la sytaxe a été très largement reprise mais on est très loin du "C with classes" du début.
Pas forcément, il faut reconstruire le paquet. Il y a un gain lorsqu'il faut downloader, mais après c'est plus lent. Si t'as une excellent connexion internet, ça ne sera peut-être pas toujours un gain.
Ca peut par contre baisser la charge et la bande passante côté serveur, certe ça prend plus de place mais l'espace disque est moins cher que la bande passante (et tu le paye qu'une fois).
# time yum -C search mutt
[...]
real 0m14.672s
user 0m10.161s
sys 0m2.584s
#
14 secondes, je trouve que c'est long pour une recherche locale. Surtout que sur une debian qui est moins puissante que la machine où la redhat (5.1) est installée :
$ time apt-cache search mutt
[...]
real 0m2.404s
user 0m1.256s
sys 0m0.236s
$
Et la debian me sorte nettement plus de packages (35 différents contre 2 fois le même packages pour la redhat).
Pour faire la completion de code, j'utilise omnicppcomplete [http://www.vim.org/scripts/script.php?script_id=1520]. Dans mon système de makefile, j'ai rajouté une target dependdirs qui affiche tous les répertoires où trouver des include, avec un tout petit script, je peux donc générer le fichier de tags dans chaque répertoire, et la completion marche à merveille.
Est-ce que en se connectant en ssh sur le modem/routeur, il n'y a pas moyen changer le port d'écoute du serveur ssh interne ? Si c'est un serveur dropbear (courant pour l'embarqué), il faut regarder d'où il est lancé et changer le script pour ajouter l'option -p qui va bien (il est peut-être lancé par inetd, il faut alors changer la conf de inetd pour écouter sur un autre port)
Le programme formail (qui est livré avec procmail) permet de manipuler les en-têtes d'un mail. On utilise souvent procmail avec formail pour la distribution locale de mails (et même bien plus).
Tu peux regarder dans la man page procmailex(5) qui donne un bon nombre d'exemples.
Sinon je trouve ta solution au contraire très propre (surtout par rapport à la mienne), mon bashrc ne permet pas non plus ta commande si on ne met pas le --norc.
J'essaierai de poster la partie de bashrc qu'll faut dès que possible.
Dans le .bashrc il suffit de mettre simplement à la fin
if [ "$BASH_START_COMMAND" ]
then
PROMPT_COMMAND="$BASH_START_COMMAND;unset PROMPT_COMMAND"
fi
Et démarrer xterm avec la variable BASH_START_COMMAND contenant la commande à executer. Dans ton cas
[^] # Re: C & Cie
Posté par Étienne . En réponse à la dépêche Sortie de Vala 0.1.6. Évalué à 3.
Pour trier on va alors instancier un objet MonComparator et le passer à la fonction Collection.sort().
Avec les templates, l'algorithme std::sort prend en paramètre une fonction, non pas un pointeur de fonction comme c'est le cas en C avec la fonction qsort mais un nom de fonction, le compilateur étant en charge de générer le code avec la bonne fonction. la declaration de std::sort ressemble à ça :
Pour trier on va alors faire
A la compilation, on déclare une nouvelle fonction sort qui prend en troisième paramètre une classe de type MonComparateur.
Les différence entre les deux approches :
- La principale c'est que l'approche template implémente une nouvelle fonction std::sort pour chaque types de paramètres différents, si je réutilise ma fonction std::sort() avec un autre comparateur (std::less par exemple), j'aurai une deuxième fonction sort prenant des paramêtres différents.
- Avec les templates, mon comparateur compare directement le type qu'il souhaite et n'a pas besoin de "caster" les Object vers le type souhaiter, on a donc une erreur dès la compilation en cas d'utilisation d'un comparateur sur un mauvais type (ceci n'est plus vrai il me semble en Java5 et en .Net2, l'interface Comparator étant une interface generique qui prend en paramètre le type comparé).
C'est vraiment important de saisir qu'avec les template, à chaque appel à une fonction avec des paramêtre différent, le compilateur crée un nouvelle fonction qui s'appel de la même façon que si elle était apellée directement.
C'est un exemple volontairement simple qui ne couvre pas tout ce qu'on peut faire ni avec l'héritage, ni avec les templates mais qui, je l'espère, permet de saisir la différence technique.
[^] # Re: C & Cie
Posté par Étienne . En réponse à la dépêche Sortie de Vala 0.1.6. Évalué à 2.
[^] # Re: C & Cie
Posté par Étienne . En réponse à la dépêche Sortie de Vala 0.1.6. Évalué à 2.
Je connais très peu java, l'impression que j'en ai est que la seule différence c'est qu'en Java, l'opérateur de comparaison doit faire des casts vers l'objet à comparer là où le C++, resolvant le type à la compilation ne le fait pas (par extension, le C++ n'a pas besoin non plus besoin que la classe à trier hérite de la class List mais qu'à la compilation on trouve les fonctions dont l'algorithme à besoin). Sinon il semble bien que ce soit identique.
[^] # Re: C & Cie
Posté par Étienne . En réponse à la dépêche Sortie de Vala 0.1.6. Évalué à 2.
J'avoue que j'ignore ce qui justifie qu'on n'ai qu'un constructeur prenant un "const char*".
[^] # Re: C & Cie
Posté par Étienne . En réponse à la dépêche Sortie de Vala 0.1.6. Évalué à 3.
Ce n'est pas une limite du modèle objet c'est un choix de ne pas l'utiliser dans certains cas.
Si on n'avait pas de template aussi puissant en C++, nul doute que la librairie standard aurait ressemblé d'avantage à QtCore, mais il se trouve que, en plus du modèle objet, on dispose de mechanismes particulièrement puissants qui ont été utilisés.
[^] # Re: C & Cie
Posté par Étienne . En réponse à la dépêche Sortie de Vala 0.1.6. Évalué à 3.
C'est faux, la généricité n'est pas du tout la même avec des interfaces et des templates.
Ca en fait un modèle un peu bancal, un coup on a un objet, un coup on a un template, ...
C'est un langage multi-paradigme et on utilise celui qui correspond le mieux à l'endroit où on en a besoin. D'ailleurs la STL ce n'est pas un coup un objet un coup un template c'est des templates partout.
Ta critique revient à dire que, par exemple, on ne devrait pas mélanger le multithreading et le multiprocess, mais chaque chose a son avantage dans différentes situations et pour des problématiques différentes.
[^] # Re: C & Cie
Posté par Étienne . En réponse à la dépêche Sortie de Vala 0.1.6. Évalué à 2.
Je suis pas là pour faire un cours de C++ mais ce que tu me dis là se résout par exemple en utilisant un std::stringstream pour voir ta chaine de charactère comme un flux puis utiliser std::getline en lui fournissant ton token. Pour assembler par exemple un vecteur de strings en une seule string séparée par un token, tu vas utiliser std::copy avec un std::ostream_iterator. Il est vrai que ça demande d'être familier avec les différents composants fournis par la STL pour pouvoir jongler avec et que c'est plus long à apprendre que QtCore par exemple.
La STL n'a pas vocation à prévoir tous les usages. Si je prend l'exemple de Qt, la classe QString me fournie les fonctions toUtf8(), toAscii() et quelques autres, bien sûr elle ne founit pas sous forme de fonctions membre tous les encodages possible. Avec la STL, il faudra passer par un std::copy() par exemple et fournir un functor qui convertis d'un encodage à un autre, mais tout est fait pour être générique.
Je comprend qu'on ne soit pas familier avec ce genre de chose et qu'on préfère avoir des fonctions membres pour tous les usages mais ce n'est pas la philosophie de la STL. En même temps libre à chacun de ne pas l'utiliser mais c'est souvent plus à cause de la trop grande généricité qu'à cause d'une vrai impossibilité.
Etienne
[^] # Re: C & Cie
Posté par Étienne . En réponse à la dépêche Sortie de Vala 0.1.6. Évalué à 3.
Je ne vois pas trop ce que tu entend par "modèle objet dans c++", la STL est ce qu'elle est pour privilégier les souplesse et les performances, la STL utilise de façon très intensive les templates plutôt que l'héritage et les fonctions virtuelles pour gérer la généricité car, la résolution se faisant à la compilation, c'est beaucoup plus rapide.
Pour prendre un exemple, pour tous les containers on peut fournir son propre allocateur de mémoire. Pour "faire plus objet", on aurait pus avoir à fournir au constructeur une instance d'une classe héritant de IAllocator, ce qui aurait induit un appel à une fonction virtuelle pour chaque allocation. Le choix qui a été fait est de fournir une classe en paramètre template, ce qui permet de déterminer l'appel de fonction dès la compilation.
Le C++ permet d'utiliser plusieurs paradigmes pour la généricité, la STL a fait le choix d'utiliser les templates ça ne veut pas dire qu'on ne peux pas utiliser autre chose et qu'on ne peux pas coder de façon plus "orienté objet" en C++.
[^] # Re: C & Cie
Posté par Étienne . En réponse à la dépêche Sortie de Vala 0.1.6. Évalué à 2.
Par exemple si je veux trier une std::list, un std::vector ou un autre container sequentiel, je ferais de la même façon
Comme ceci, je peux utiliser le container qui est le plus adapté (fournit par la stl ou un autre). C'est sans doute cela qui est déroutant quand on n'est pas habitué.
Le reproche que je fais à la stl c'est de n'être pas assez complète, ceci étant dû à la façon de faire évoluer le standard au sein du commité. C'est pour celà qu'on a très souvent recours à un bibliothèque comme boost (dont certains éléments passe dans le standard comme les shared_ptr).
[^] # Re: C & Cie
Posté par Étienne . En réponse à la dépêche Sortie de Vala 0.1.6. Évalué à 1.
Comme à peu près tous les langage, Objective-C, Java, C# et autres compris.
[^] # Re: C & Cie
Posté par Étienne . En réponse à la dépêche Sortie de Vala 0.1.6. Évalué à 3.
C'est à dire ?
[^] # Re: C & Cie
Posté par Étienne . En réponse à la dépêche Sortie de Vala 0.1.6. Évalué à 5.
Une implémentation de C++ qui ne fournit pas de std::string n'est pas du C++, car la STL est justement décrite dans le standard du C++.
Le langage est composé d'une syntaxe et d'une bibliothèque standard.
Pour prendre ton exemple des MFC, c'est exactement l'exemple où on fait non pas du C++ mais du "C with classes" et ça n'utilise de C++ que les classes (on aurait pû faire aussi dégueulasse en Objective-C soit dit en passant).
Qu'on puisse ne pas utiliser la bibliothèque standard est vrai dans tous les langages. Mais va faire un tour sur les newsgroups (fr.)?comp.lang.c++ ou lis les livres de Bjarne Stroustrup, Herb Sutter ou Andreï Alexandrescu pour voir que le C++ est loin d'être une "simple surcouche au C" et qu'on ne programme pas du tout de la même façon en C et C++.
Etienne
[^] # Re: C & Cie
Posté par Étienne . En réponse à la dépêche Sortie de Vala 0.1.6. Évalué à 5.
Je pense que justement le C++ n'est pas une couche au dessus du C, contrairement à Objective-C. C'est un autre langage qui s'interface très facilement avec le C mais c'est plus à voir comme un autre langage. Pour illustrer mon propos, en C++, on n'utilise pas (en tout cas c'est plus que déconseillé) de chaine de charactères en char* mais des std::string, de même qu'on utilise pas de pointeurs pour faire des tableaux mais des std::vector<> (ou std::array encore en tr1). Il y a très peu de choses que l'on fait en C++ de la même manière qu'on le fait en C. Certe la sytaxe a été très largement reprise mais on est très loin du "C with classes" du début.
Etienne
[^] # Re: Radio Nostalgie
Posté par Étienne . En réponse au journal Gentoo file un mauvais coton. Évalué à 2.
Etienne
[^] # Re: Non évènement
Posté par Étienne . En réponse à la dépêche Sortie de rpm 5.0.0. Évalué à 1.
Merci
Etienne
[^] # Re: Non évènement
Posté par Étienne . En réponse à la dépêche Sortie de rpm 5.0.0. Évalué à 1.
Ca peut par contre baisser la charge et la bande passante côté serveur, certe ça prend plus de place mais l'espace disque est moins cher que la bande passante (et tu le paye qu'une fois).
Etienne
[^] # Re: Non évènement
Posté par Étienne . En réponse à la dépêche Sortie de rpm 5.0.0. Évalué à 2.
14 secondes, je trouve que c'est long pour une recherche locale. Surtout que sur une debian qui est moins puissante que la machine où la redhat (5.1) est installée :
Et la debian me sorte nettement plus de packages (35 différents contre 2 fois le même packages pour la redhat).
[^] # Re: Vim
Posté par Étienne . En réponse au journal Qu'est-ce qu'un outils de développement de rève ?. Évalué à 1.
Etienne
[^] # Re: Vim
Posté par Étienne . En réponse au journal Qu'est-ce qu'un outils de développement de rève ?. Évalué à 1.
A titre personnel, j'utilise directement gdb avec l'option -tui pour visualiser le code correctement.
Etienne
[^] # Re: je n'ai pas trouvé
Posté par Étienne . En réponse au journal Qu'est-ce qu'un outils de développement de rève ?. Évalué à 1.
Pour faire la completion de code, j'utilise omnicppcomplete [http://www.vim.org/scripts/script.php?script_id=1520]. Dans mon système de makefile, j'ai rajouté une target dependdirs qui affiche tous les répertoires où trouver des include, avec un tout petit script, je peux donc générer le fichier de tags dans chaque répertoire, et la completion marche à merveille.
On peut rajouter taglist [http://vim-taglist.sourceforge.net/] pour naviguer dans les classes et echofunc [http://vim.sourceforge.net/scripts/script.php?script_id=1735] pour afficher la signature d'une fonction lors de l'ouverture de la parenthèse.
[^] # Re: Mauvais modem/routeur
Posté par Étienne . En réponse au message ssh possible uniquement depuis le réseau local. Évalué à 1.
Etienne
[^] # Re: Pour les feignasses
Posté par Étienne . En réponse au journal Monkey Studio 2 : Second Preview, c'est partis !. Évalué à 2.
Non, KDE s'est plutot tourné vers cmake et je ne crois pas qu'ils aient jamais utilisé qmake. En tout cas avant cmake c'était les autotools.
Etienne
# Utilisation de getpass
Posté par Étienne . En réponse au message [Admin] Construire des mots de passe forts mais facilement reconstructibles. Évalué à 1.
import sha, base64, getpass
[...]
master_seed = getpass.getpass("master seed: ")
Etienne
# Modification des en-têtes
Posté par Étienne . En réponse au message Analyser et modifier les en-tête d'un mail. Évalué à 1.
Tu peux regarder dans la man page procmailex(5) qui donne un bon nombre d'exemples.
Etienne
[^] # Re: des essais
Posté par Étienne . En réponse au message Démarrer un shell avec un programme dedans.. Évalué à 1.
J'essaierai de poster la partie de bashrc qu'll faut dès que possible.
Dans le .bashrc il suffit de mettre simplement à la fin
Et démarrer xterm avec la variable BASH_START_COMMAND contenant la commande à executer. Dans ton cas
BASH_START_COMMAND=vim xterm