J'aimerais mettre en place une interface =E0-la IEnumerable<T>. En 2
mots, c'est une classe C# de base pour toutes les collections
enumerables, qui permet de traiter de fa=E7on uniforme list et vector
par exemple, lorsqu'on a des boucles du types "foreach ()".
J'aimerais faire la m=EAme chose, ie. j'ai une interface "Interface" que
j'aimerais voir avec 2 m=E9thodes abstraites : "AddChild (Children*)" et
"getChildren (Children*)". Mais que donner comme type de retour =E0
"getChildren" ?
Le probl=E8me est que j'aimerais que les utilisateurs de l'interface ne
voient pas si c'est une std::list ou std::vector ou autre, qu'ils
aient juste le moyen de faire quelque chose du type for_each dedans
(genre BOOST_FOREACH).
Vu que c'est une m=E9thode virtuelle =E0 impl=E9menter dans les classes
d'impl=E9mentation, je ne peux pas en faire une m=E9thode avec template,
donc les solutions =E0 base de "renvoyer une paire d'iterator begin/end"
ou du boost:range me semblent =E9chouer (oblig=E9 de dire si l'iterator
vient de list ou vector ou autre).
Il y aurait la possibilit=E9 de passer en param=E8tre template =E0 cette
interface le container utilis=E9, mais =E7a a le side effect de changer le
type, donc je ne pourrai pas stocker des impl=E9mentations avec
diff=E9rents containers dans un m=EAme vector par exemple. En plus =E7a
couple trop.
La seule chose que je vois est de faire un Adaptor pour iterator,
genre IIterator<T> qui forwarde les appels, puis de tout faire passer
par =E7a (ie. retourner un tel objet/range).
Vu que =E7a demande pas mal d'efforts, je voulais vous demander si vous
n'avez pas une meilleure id=E9e. Ou alors mon id=E9e de d=E9part n'est pas
un bon design ?
Merci,
Michael, qui revient quelques ann=E9es plus tard :)
On Fri, 22 Jan 2010 16:12:27 -0800 (PST), Mic Mon : Tu essaies d'implémenter un truc assez compliqué, pour pouvoir accomoder une fonctionnalité dont tu n'es pas sûr d'avoir besoin. C'est donc un cas typique de généralisation abusive.
Oui en fait c'est aussi ce que dit Meyers dans Effective STL, il recommande ne pas essayer de généraliser sur les conteneurs.
Mais je trouve étonnant que le type sous-jacent soit toujours obligé d'être visible.
Utilise plutôt des typedef pour pouvoir changer le conteneur facilement en cas de besoin. Et en attendant, tu peux suivre une des règles de base : utilise std::vector<> tant que tu n'as pas de bonne raison d'utiliser autre chose. Et attends pour en changer que ton profiler t'indique un coût important de vector<>::insert().
Ok, c'est ce que je vais faire merci.
Mic
On 23 jan, 02:02, Fabien LE LEZ <grams...@gramster.com> wrote:
On Fri, 22 Jan 2010 16:12:27 -0800 (PST), Mic Mon
<drag.cor...@gmail.com>:
Tu essaies d'implémenter un truc assez compliqué, pour pouvoir
accomoder une fonctionnalité dont tu n'es pas sûr d'avoir besoin.
C'est donc un cas typique de généralisation abusive.
Oui en fait c'est aussi ce que dit Meyers dans Effective STL, il
recommande ne pas essayer de généraliser sur les conteneurs.
Mais je trouve étonnant que le type sous-jacent soit toujours obligé
d'être visible.
Utilise plutôt des typedef pour pouvoir changer le conteneur
facilement en cas de besoin. Et en attendant, tu peux suivre une des
règles de base : utilise std::vector<> tant que tu n'as pas de bonne
raison d'utiliser autre chose. Et attends pour en changer que ton
profiler t'indique un coût important de vector<>::insert().
On Fri, 22 Jan 2010 16:12:27 -0800 (PST), Mic Mon : Tu essaies d'implémenter un truc assez compliqué, pour pouvoir accomoder une fonctionnalité dont tu n'es pas sûr d'avoir besoin. C'est donc un cas typique de généralisation abusive.
Oui en fait c'est aussi ce que dit Meyers dans Effective STL, il recommande ne pas essayer de généraliser sur les conteneurs.
Mais je trouve étonnant que le type sous-jacent soit toujours obligé d'être visible.
Utilise plutôt des typedef pour pouvoir changer le conteneur facilement en cas de besoin. Et en attendant, tu peux suivre une des règles de base : utilise std::vector<> tant que tu n'as pas de bonne raison d'utiliser autre chose. Et attends pour en changer que ton profiler t'indique un coût important de vector<>::insert().
Ok, c'est ce que je vais faire merci.
Mic
Mic Mon
On 23 jan, 03:28, Fabien LE LEZ wrote:
On Fri, 22 Jan 2010 16:31:03 -0800 (PST), Mic Mon : > return make_pair ( make_iterator (mon_conteneur_connu.begin(), >mon_conteneur_connu.end()));
N'insère pas de retours à la ligne au milieu de tes lignes de code, c'est très difficile à lire !
En fait je poste depuis groups.google.fr parce que je change tout le temps de connexion en ce moment, c'est lui qui a mis le newline :(
make_iterator (...) renvoie un objet de quel type ? make_pair (...) renvoie un objet de quel type ? Le type renvoyé est-il bien convertible en un "boost::range<IIterator<MonTypeConnu>, IIterator<MonTypeConnu> >" ?
D'ailleurs, peut-on construire un objet de type "boost::range<IITerator<Type>, IIterator<Type> >", sachant que IIterator<Type> est une classe abstraite ?
Oui j'ai écrit trop vite. En fait je voulais dire boost:range<shared_ptr<IIterator<Type>>> en ajustant les 2 ou 3 lignes de mon code comme il faut, désolé. Mais ça commence à faire beaucou p d'indirections tout ça (ceci dit ça marcherait il me semble).
En particulier, std::make_pair<> effectue une copie de ses arguments. Du coup, il transforme deux Iterator<> en un pair<Iterator<>,Iterator<>>. Il ne peut pas fonctionner avec des IIterator car cette classe est abstraite : on ne peut pas en créer d'instances.
Oui en fait dans la version non fausse de ce que je voulais dire, c'est boost::make_iterator_range mais c'est pareil.
Mic
On 23 jan, 03:28, Fabien LE LEZ <grams...@gramster.com> wrote:
On Fri, 22 Jan 2010 16:31:03 -0800 (PST), Mic Mon
<drag.cor...@gmail.com>:
> return make_pair ( make_iterator (mon_conteneur_connu.begin(),
>mon_conteneur_connu.end()));
N'insère pas de retours à la ligne au milieu de tes lignes de code,
c'est très difficile à lire !
En fait je poste depuis groups.google.fr parce que je change tout le
temps de connexion en ce moment, c'est lui qui a mis le newline :(
make_iterator (...) renvoie un objet de quel type ?
make_pair (...) renvoie un objet de quel type ?
Le type renvoyé est-il bien convertible en un
"boost::range<IIterator<MonTypeConnu>, IIterator<MonTypeConnu> >" ?
D'ailleurs, peut-on construire un objet de type
"boost::range<IITerator<Type>, IIterator<Type> >", sachant que
IIterator<Type> est une classe abstraite ?
Oui j'ai écrit trop vite. En fait je voulais dire
boost:range<shared_ptr<IIterator<Type>>> en ajustant les 2 ou 3 lignes
de mon code comme il faut, désolé. Mais ça commence à faire beaucou p
d'indirections tout ça (ceci dit ça marcherait il me semble).
En particulier, std::make_pair<> effectue une copie de ses arguments.
Du coup, il transforme deux Iterator<> en un
pair<Iterator<>,Iterator<>>.
Il ne peut pas fonctionner avec des IIterator car cette classe est
abstraite : on ne peut pas en créer d'instances.
Oui en fait dans la version non fausse de ce que je voulais dire,
c'est boost::make_iterator_range mais c'est pareil.
On Fri, 22 Jan 2010 16:31:03 -0800 (PST), Mic Mon : > return make_pair ( make_iterator (mon_conteneur_connu.begin(), >mon_conteneur_connu.end()));
N'insère pas de retours à la ligne au milieu de tes lignes de code, c'est très difficile à lire !
En fait je poste depuis groups.google.fr parce que je change tout le temps de connexion en ce moment, c'est lui qui a mis le newline :(
make_iterator (...) renvoie un objet de quel type ? make_pair (...) renvoie un objet de quel type ? Le type renvoyé est-il bien convertible en un "boost::range<IIterator<MonTypeConnu>, IIterator<MonTypeConnu> >" ?
D'ailleurs, peut-on construire un objet de type "boost::range<IITerator<Type>, IIterator<Type> >", sachant que IIterator<Type> est une classe abstraite ?
Oui j'ai écrit trop vite. En fait je voulais dire boost:range<shared_ptr<IIterator<Type>>> en ajustant les 2 ou 3 lignes de mon code comme il faut, désolé. Mais ça commence à faire beaucou p d'indirections tout ça (ceci dit ça marcherait il me semble).
En particulier, std::make_pair<> effectue une copie de ses arguments. Du coup, il transforme deux Iterator<> en un pair<Iterator<>,Iterator<>>. Il ne peut pas fonctionner avec des IIterator car cette classe est abstraite : on ne peut pas en créer d'instances.
Oui en fait dans la version non fausse de ce que je voulais dire, c'est boost::make_iterator_range mais c'est pareil.
Mic
Mic Mon
On 23 jan, 07:55, ld wrote:
> J'aimerais mettre en place une interface à-la IEnumerable<T>. En 2 > mots, c'est une classe C# de base pour toutes les collections > enumerables, qui permet de traiter de façon uniforme list et vector > par exemple, lorsqu'on a des boucles du types "foreach ()".
quelle est le probleme avec la STL ?
J'aurais aimé ne pas montrer à l'extérieur quel conteneur STL est utilisé par la collection. Or le type d'iterator en dépend, et il semble que du coup on est obligé de rendre l'information publique (et fixée) par un typedef. Sinon il faudrait abstraire le type d'iterator comme dans une branche du thread, mais c'est trop lourd.
Je pense qu'il faut bien definir ton probleme et distinguer deux cas. Soit le conteneur est connu a la compilation et dans ce cas la STL devrait satisfaire la pluspart des besoins (cf liens ci-dessus). Soit le conteneur n'est pas connu a la compilation et dans ce cas il y a beaucoup a faire/ecrire pour arriver au meme niveau que la STL et mieux vaut chercher une bibliotheque qui fait deja cela.
Oui voilà, on pourrait dire que le conteneur n'est pas connu à la compil vu qu'il dépendrait de l'implémentation de l'interface.
Sinon ce n'est pas forcement le bon langage car l'utiliser dans de tel cas reviendrait a ecrire un "interpreteur". Ce n'est biensur pas impossible, mais cela veut dire ecrire une sorte de framework a-la-STL en tout dynamique que l'on appelle un "Adaptive Object Model". Mais si tel est ton besoin, peut-etre considerer un langage plus dynamique permettra de resoudre le probleme plus efficacement.
Ah ok ça a un nom. Je vais regarder, merci.
> Vu que ça demande pas mal d'efforts, je voulais vous demander si vous > n'avez pas une meilleure idée. Ou alors mon idée de départ n'est pas > un bon design ?
Peut-etre regarder du cote de Boost, Qt, Poco, Root pour voir ce qui a deja ete fait serait un gain de temps? Une alternative rapide consisterait a utiliser la STL (ou boost) avec boost::variant ou boost::any suivant les besoins.
Merci pour les pointeurs !
Mic
On 23 jan, 07:55, ld <laurent.den...@gmail.com> wrote:
> J'aimerais mettre en place une interface à-la IEnumerable<T>. En 2
> mots, c'est une classe C# de base pour toutes les collections
> enumerables, qui permet de traiter de façon uniforme list et vector
> par exemple, lorsqu'on a des boucles du types "foreach ()".
quelle est le probleme avec la STL ?
J'aurais aimé ne pas montrer à l'extérieur quel conteneur STL est
utilisé par la collection. Or le type d'iterator en dépend, et il
semble que du coup on est obligé de rendre l'information publique (et
fixée) par un typedef. Sinon il faudrait abstraire le type d'iterator
comme dans une branche du thread, mais c'est trop lourd.
Je pense qu'il faut bien definir ton probleme et distinguer deux cas.
Soit le conteneur est connu a la compilation et dans ce cas la STL
devrait satisfaire la pluspart des besoins (cf liens ci-dessus). Soit
le conteneur n'est pas connu a la compilation et dans ce cas il y a
beaucoup a faire/ecrire pour arriver au meme niveau que la STL et
mieux vaut chercher une bibliotheque qui fait deja cela.
Oui voilà, on pourrait dire que le conteneur n'est pas connu à la
compil vu qu'il dépendrait de l'implémentation de l'interface.
Sinon ce n'est pas forcement le bon langage car l'utiliser dans de tel
cas reviendrait a ecrire un "interpreteur". Ce n'est biensur pas
impossible, mais cela veut dire ecrire une sorte de framework a-la-STL
en tout dynamique que l'on appelle un "Adaptive Object Model". Mais si
tel est ton besoin, peut-etre considerer un langage plus dynamique
permettra de resoudre le probleme plus efficacement.
Ah ok ça a un nom. Je vais regarder, merci.
> Vu que ça demande pas mal d'efforts, je voulais vous demander si vous
> n'avez pas une meilleure idée. Ou alors mon idée de départ n'est pas
> un bon design ?
Peut-etre regarder du cote de Boost, Qt, Poco, Root pour voir ce qui a
deja ete fait serait un gain de temps? Une alternative rapide
consisterait a utiliser la STL (ou boost) avec boost::variant ou
boost::any suivant les besoins.
> J'aimerais mettre en place une interface à-la IEnumerable<T>. En 2 > mots, c'est une classe C# de base pour toutes les collections > enumerables, qui permet de traiter de façon uniforme list et vector > par exemple, lorsqu'on a des boucles du types "foreach ()".
quelle est le probleme avec la STL ?
J'aurais aimé ne pas montrer à l'extérieur quel conteneur STL est utilisé par la collection. Or le type d'iterator en dépend, et il semble que du coup on est obligé de rendre l'information publique (et fixée) par un typedef. Sinon il faudrait abstraire le type d'iterator comme dans une branche du thread, mais c'est trop lourd.
Je pense qu'il faut bien definir ton probleme et distinguer deux cas. Soit le conteneur est connu a la compilation et dans ce cas la STL devrait satisfaire la pluspart des besoins (cf liens ci-dessus). Soit le conteneur n'est pas connu a la compilation et dans ce cas il y a beaucoup a faire/ecrire pour arriver au meme niveau que la STL et mieux vaut chercher une bibliotheque qui fait deja cela.
Oui voilà, on pourrait dire que le conteneur n'est pas connu à la compil vu qu'il dépendrait de l'implémentation de l'interface.
Sinon ce n'est pas forcement le bon langage car l'utiliser dans de tel cas reviendrait a ecrire un "interpreteur". Ce n'est biensur pas impossible, mais cela veut dire ecrire une sorte de framework a-la-STL en tout dynamique que l'on appelle un "Adaptive Object Model". Mais si tel est ton besoin, peut-etre considerer un langage plus dynamique permettra de resoudre le probleme plus efficacement.
Ah ok ça a un nom. Je vais regarder, merci.
> Vu que ça demande pas mal d'efforts, je voulais vous demander si vous > n'avez pas une meilleure idée. Ou alors mon idée de départ n'est pas > un bon design ?
Peut-etre regarder du cote de Boost, Qt, Poco, Root pour voir ce qui a deja ete fait serait un gain de temps? Une alternative rapide consisterait a utiliser la STL (ou boost) avec boost::variant ou boost::any suivant les besoins.
Je ne comprends pas non plus l'intérêt d'utiliser boost::range. Mais je ne connais pas bien cette librairie.
Je l'utilise parce que ça dit exactement le sens de l'objet retourné à l'appelant, c'est déjà implémenté et robuste, et ça permet le BOOST_FOREACH par exemple qui est bien pratique.
Mic
On 23 jan, 11:45, FX <fx.sp...@laposte.net> wrote:
Je ne comprends pas non plus l'intérêt d'utiliser boost::range. Mais je
ne connais pas bien cette librairie.
Je l'utilise parce que ça dit exactement le sens de l'objet retourné à
l'appelant, c'est déjà implémenté et robuste, et ça permet le
BOOST_FOREACH par exemple qui est bien pratique.
Je ne comprends pas non plus l'intérêt d'utiliser boost::range. Mais je ne connais pas bien cette librairie.
Je l'utilise parce que ça dit exactement le sens de l'objet retourné à l'appelant, c'est déjà implémenté et robuste, et ça permet le BOOST_FOREACH par exemple qui est bien pratique.
Mic
Fabien LE LEZ
On Sun, 24 Jan 2010 01:16:33 -0800 (PST), Mic Mon :
Mais je trouve étonnant que le type sous-jacent soit toujours obligé d'être visible.
C'est le principe du modèle C++ : écrire MaClasse objet; c'est allouer un objet de type "MaClasse" sur la pile, ce qui ne peut se faire que si le compilo peut calculer sizeof(MaClasse). Du coup, tous les membres doivent être visibles (même les membres privés).
Certes, on peut le contourner (via l'idiome pimpl par exemple), mais ce n'est que ça : un contournement.
On Sun, 24 Jan 2010 01:16:33 -0800 (PST), Mic Mon
<drag.cortex@gmail.com>:
Mais je trouve étonnant que le type sous-jacent soit toujours obligé
d'être visible.
C'est le principe du modèle C++ : écrire
MaClasse objet;
c'est allouer un objet de type "MaClasse" sur la pile, ce qui ne peut
se faire que si le compilo peut calculer sizeof(MaClasse).
Du coup, tous les membres doivent être visibles (même les membres
privés).
Certes, on peut le contourner (via l'idiome pimpl par exemple), mais
ce n'est que ça : un contournement.
On Sun, 24 Jan 2010 01:16:33 -0800 (PST), Mic Mon :
Mais je trouve étonnant que le type sous-jacent soit toujours obligé d'être visible.
C'est le principe du modèle C++ : écrire MaClasse objet; c'est allouer un objet de type "MaClasse" sur la pile, ce qui ne peut se faire que si le compilo peut calculer sizeof(MaClasse). Du coup, tous les membres doivent être visibles (même les membres privés).
Certes, on peut le contourner (via l'idiome pimpl par exemple), mais ce n'est que ça : un contournement.