class Points : public vector<CPoint> {
Ce n'est pas en général une bonne idée d'hériter de std::vector.
Il n'a pas été conçu pour servir de classe de base.
Oui mais si ça marche, j'avoue que c'est le principal.
Respecter la norme pour la norme, ce n'est pas mon truc.
En un truc qui la respecte à la lettre, et un autre un peu moins mais
valable et plus lisible, mon choix est vite fait.
vector<CPoint>* pTbl=new Points();
//.......
delete pTbl;
Ceci ne "marche" pas car le destructeur de Points n'est pas appelé lors du
delete.
class Points : public vector<CPoint> {
Ce n'est pas en général une bonne idée d'hériter de std::vector.
Il n'a pas été conçu pour servir de classe de base.
Oui mais si ça marche, j'avoue que c'est le principal.
Respecter la norme pour la norme, ce n'est pas mon truc.
En un truc qui la respecte à la lettre, et un autre un peu moins mais
valable et plus lisible, mon choix est vite fait.
vector<CPoint>* pTbl=new Points();
//.......
delete pTbl;
Ceci ne "marche" pas car le destructeur de Points n'est pas appelé lors du
delete.
class Points : public vector<CPoint> {
Ce n'est pas en général une bonne idée d'hériter de std::vector.
Il n'a pas été conçu pour servir de classe de base.
Oui mais si ça marche, j'avoue que c'est le principal.
Respecter la norme pour la norme, ce n'est pas mon truc.
En un truc qui la respecte à la lettre, et un autre un peu moins mais
valable et plus lisible, mon choix est vite fait.
vector<CPoint>* pTbl=new Points();
//.......
delete pTbl;
Ceci ne "marche" pas car le destructeur de Points n'est pas appelé lors du
delete.
kanze wrote on 13/09/2006 10:40:typedef peut aider si tu t'obliges à changer tes
interfaces, cela risque de ne pas tout régler si tu
utilises des libs externes attendant un CPoint*
Si c'est une classe à lui, il a toutes les chances à avoir
accès à toutes les fonctions concernées.
soit, mais cela peut être la classe (archi basic) des MFC ...
La façon naturelle en C++ de passer un paramètre par
référence, c'est d'utiliser une référence. Si on a un
problème avec des bibliothèques externe, on le résoud en
général avec un wrapper (modèle décorateur) qui fait les
conversions nécessaires.
si l'objet décoré est le vector<> et si le decorator est celui
qui fournit un opérateur de cast vers CPoint*, le problème
restera identique: obtenir ce pointeur depuis le vector<>.
class Points : public vector<CPoint> {
Ce n'est pas en général une bonne idée d'hériter de
std::vector. Il n'a pas été conçu pour servir de classe de
base.
cela est propre à vector ou est vrai pour la plupart des
classes templates de la STL ?
public:
Points(){}
operator CPoint* () { return begin(); }
Et ça, évidemment, ne se compile pas, sinon que par hazard
avec un ancien compilateur. (Il se compilait avec VC++ 6.0
ou g++ 2.95.2, mais il ne se compile pas avec VC++ 2005 ni
avec g++ 4.1.0.)
le "hasard" est ici simplement la définition des libs fournies
avec les compilo cités, c'est assez déterministe comme hasard.
le problème connu comme "ne se compile pas" est lié à la
version de la STL utilisé, non à celle du compilateur; dès
lors indiquer que cela ne peut fonctionner avec telle version
de la STL, même si cela pouvait être valide avec telle autre
version serait plus instructif.
cela posant d'ailleurs le problème de l'identification de la
version de la STL utilisée, comment la connaitre ? (j'ai noté
un copyright en commentaire en fin de ses fichiers, ce n'est
pas vraiment la réponse attendue).
cela interroge également sur la compatibilité ascendante
des STL, n'étant pas adepte du hasard, comment celle-ci
est garantie ?
plus généralement, existe-t-il une définition normative
des API (donc hors implémentation) qu'une librairie dite
STL doit satisfaire ?
pour revenir sur le fond de ma proposition, que je
reformule en: "est-il possible de changer une déclaration
a-la-mano (new CPoints, etc) par une utilsation de vector<>
*sans* devoir modifier toutes ses procédures de traitement ?"
- je pense inintéressant de savoir si "begin()" se compile
ou si "return &at(0);" est mieux; on codera cet opérateur
une seule et unique fois, il peut changer, j'ai pu donner
un mauvais nom, on s'en tape
- car le point est bcp plus:
* vector<> jouant (déjà) un role de décorateur:
peux-t-on attendre d'une prochaine version (Cf post de
Marc) la disponibilité d'un tel opérateur de cast ?
* ce cast n'étant pas présent aujourd'hui, peut-on malgré
tout supposer un stockage linéaire et continu des éléments
du vector<T> ? (si ce n'est pas le cas, un pointeur T* est
inutilisable et les joyeux iterators obligeatoires)
* dans le même temps s'il est présent, les opérateurs []
vont devenir confus.
operator const CPoint* () const { return begin(); }
Pareil.
oui, pareil, il suffit d'utiliser &at(0), n'importe quel
developpeur sait le faire.Et qui permet aussi :
std::vector< CPoint >* pv = new Points ;
delete pv ; // Comportement indéfini.
indéfini parce que vector<> ne définit pas son destructeur
comme virtuel; tu l'as déjà indiqué "Il n'a pas été conçu
pour servir de classe de base."
je m'interroge ici aussi sur ce choix.
la question qui reste est: peux-t-on accéder linéairement
aux élements d'un vector
(ou vector<> peut-il un decorator)?
kanze wrote on 13/09/2006 10:40:
typedef peut aider si tu t'obliges à changer tes
interfaces, cela risque de ne pas tout régler si tu
utilises des libs externes attendant un CPoint*
Si c'est une classe à lui, il a toutes les chances à avoir
accès à toutes les fonctions concernées.
soit, mais cela peut être la classe (archi basic) des MFC ...
La façon naturelle en C++ de passer un paramètre par
référence, c'est d'utiliser une référence. Si on a un
problème avec des bibliothèques externe, on le résoud en
général avec un wrapper (modèle décorateur) qui fait les
conversions nécessaires.
si l'objet décoré est le vector<> et si le decorator est celui
qui fournit un opérateur de cast vers CPoint*, le problème
restera identique: obtenir ce pointeur depuis le vector<>.
class Points : public vector<CPoint> {
Ce n'est pas en général une bonne idée d'hériter de
std::vector. Il n'a pas été conçu pour servir de classe de
base.
cela est propre à vector ou est vrai pour la plupart des
classes templates de la STL ?
public:
Points(){}
operator CPoint* () { return begin(); }
Et ça, évidemment, ne se compile pas, sinon que par hazard
avec un ancien compilateur. (Il se compilait avec VC++ 6.0
ou g++ 2.95.2, mais il ne se compile pas avec VC++ 2005 ni
avec g++ 4.1.0.)
le "hasard" est ici simplement la définition des libs fournies
avec les compilo cités, c'est assez déterministe comme hasard.
le problème connu comme "ne se compile pas" est lié à la
version de la STL utilisé, non à celle du compilateur; dès
lors indiquer que cela ne peut fonctionner avec telle version
de la STL, même si cela pouvait être valide avec telle autre
version serait plus instructif.
cela posant d'ailleurs le problème de l'identification de la
version de la STL utilisée, comment la connaitre ? (j'ai noté
un copyright en commentaire en fin de ses fichiers, ce n'est
pas vraiment la réponse attendue).
cela interroge également sur la compatibilité ascendante
des STL, n'étant pas adepte du hasard, comment celle-ci
est garantie ?
plus généralement, existe-t-il une définition normative
des API (donc hors implémentation) qu'une librairie dite
STL doit satisfaire ?
pour revenir sur le fond de ma proposition, que je
reformule en: "est-il possible de changer une déclaration
a-la-mano (new CPoints, etc) par une utilsation de vector<>
*sans* devoir modifier toutes ses procédures de traitement ?"
- je pense inintéressant de savoir si "begin()" se compile
ou si "return &at(0);" est mieux; on codera cet opérateur
une seule et unique fois, il peut changer, j'ai pu donner
un mauvais nom, on s'en tape
- car le point est bcp plus:
* vector<> jouant (déjà) un role de décorateur:
peux-t-on attendre d'une prochaine version (Cf post de
Marc) la disponibilité d'un tel opérateur de cast ?
* ce cast n'étant pas présent aujourd'hui, peut-on malgré
tout supposer un stockage linéaire et continu des éléments
du vector<T> ? (si ce n'est pas le cas, un pointeur T* est
inutilisable et les joyeux iterators obligeatoires)
* dans le même temps s'il est présent, les opérateurs []
vont devenir confus.
operator const CPoint* () const { return begin(); }
Pareil.
oui, pareil, il suffit d'utiliser &at(0), n'importe quel
developpeur sait le faire.
Et qui permet aussi :
std::vector< CPoint >* pv = new Points ;
delete pv ; // Comportement indéfini.
indéfini parce que vector<> ne définit pas son destructeur
comme virtuel; tu l'as déjà indiqué "Il n'a pas été conçu
pour servir de classe de base."
je m'interroge ici aussi sur ce choix.
la question qui reste est: peux-t-on accéder linéairement
aux élements d'un vector
(ou vector<> peut-il un decorator)?
kanze wrote on 13/09/2006 10:40:typedef peut aider si tu t'obliges à changer tes
interfaces, cela risque de ne pas tout régler si tu
utilises des libs externes attendant un CPoint*
Si c'est une classe à lui, il a toutes les chances à avoir
accès à toutes les fonctions concernées.
soit, mais cela peut être la classe (archi basic) des MFC ...
La façon naturelle en C++ de passer un paramètre par
référence, c'est d'utiliser une référence. Si on a un
problème avec des bibliothèques externe, on le résoud en
général avec un wrapper (modèle décorateur) qui fait les
conversions nécessaires.
si l'objet décoré est le vector<> et si le decorator est celui
qui fournit un opérateur de cast vers CPoint*, le problème
restera identique: obtenir ce pointeur depuis le vector<>.
class Points : public vector<CPoint> {
Ce n'est pas en général une bonne idée d'hériter de
std::vector. Il n'a pas été conçu pour servir de classe de
base.
cela est propre à vector ou est vrai pour la plupart des
classes templates de la STL ?
public:
Points(){}
operator CPoint* () { return begin(); }
Et ça, évidemment, ne se compile pas, sinon que par hazard
avec un ancien compilateur. (Il se compilait avec VC++ 6.0
ou g++ 2.95.2, mais il ne se compile pas avec VC++ 2005 ni
avec g++ 4.1.0.)
le "hasard" est ici simplement la définition des libs fournies
avec les compilo cités, c'est assez déterministe comme hasard.
le problème connu comme "ne se compile pas" est lié à la
version de la STL utilisé, non à celle du compilateur; dès
lors indiquer que cela ne peut fonctionner avec telle version
de la STL, même si cela pouvait être valide avec telle autre
version serait plus instructif.
cela posant d'ailleurs le problème de l'identification de la
version de la STL utilisée, comment la connaitre ? (j'ai noté
un copyright en commentaire en fin de ses fichiers, ce n'est
pas vraiment la réponse attendue).
cela interroge également sur la compatibilité ascendante
des STL, n'étant pas adepte du hasard, comment celle-ci
est garantie ?
plus généralement, existe-t-il une définition normative
des API (donc hors implémentation) qu'une librairie dite
STL doit satisfaire ?
pour revenir sur le fond de ma proposition, que je
reformule en: "est-il possible de changer une déclaration
a-la-mano (new CPoints, etc) par une utilsation de vector<>
*sans* devoir modifier toutes ses procédures de traitement ?"
- je pense inintéressant de savoir si "begin()" se compile
ou si "return &at(0);" est mieux; on codera cet opérateur
une seule et unique fois, il peut changer, j'ai pu donner
un mauvais nom, on s'en tape
- car le point est bcp plus:
* vector<> jouant (déjà) un role de décorateur:
peux-t-on attendre d'une prochaine version (Cf post de
Marc) la disponibilité d'un tel opérateur de cast ?
* ce cast n'étant pas présent aujourd'hui, peut-on malgré
tout supposer un stockage linéaire et continu des éléments
du vector<T> ? (si ce n'est pas le cas, un pointeur T* est
inutilisable et les joyeux iterators obligeatoires)
* dans le même temps s'il est présent, les opérateurs []
vont devenir confus.
operator const CPoint* () const { return begin(); }
Pareil.
oui, pareil, il suffit d'utiliser &at(0), n'importe quel
developpeur sait le faire.Et qui permet aussi :
std::vector< CPoint >* pv = new Points ;
delete pv ; // Comportement indéfini.
indéfini parce que vector<> ne définit pas son destructeur
comme virtuel; tu l'as déjà indiqué "Il n'a pas été conçu
pour servir de classe de base."
je m'interroge ici aussi sur ce choix.
la question qui reste est: peux-t-on accéder linéairement
aux élements d'un vector
(ou vector<> peut-il un decorator)?
Franck Branjonneau wrote on 13/09/2006 19:37:Sylvain écrivait:Franck Branjonneau wrote on 13/09/2006 01:14:void f(std::vector<CPoint>& points);
Bé d'abord parce que je découvre la STL, ensuite cela m'évite de tout
changer dans un premier temps, puis cela fait des déclarations à
rallonge :o)
inline void f(std::vector<CPoint>& points) { return f(&points[0]); }
tu plaisantes ?
Non, pourquoi ?
pour rien.
je ne suis pas payé au caractère, ça doit m'empêcher d'appréc ier.
Euh, ça permet justement d'économiser les efforts en évitant
d'avoir à modifier le code existant... Et d'économiser des
caractères si f est appelé relativement souvent.
Franck Branjonneau wrote on 13/09/2006 19:37:
Sylvain <noSpam@mail.net> écrivait:
Franck Branjonneau wrote on 13/09/2006 01:14:
void f(std::vector<CPoint>& points);
Bé d'abord parce que je découvre la STL, ensuite cela m'évite de tout
changer dans un premier temps, puis cela fait des déclarations à
rallonge :o)
inline void f(std::vector<CPoint>& points) { return f(&points[0]); }
tu plaisantes ?
Non, pourquoi ?
pour rien.
je ne suis pas payé au caractère, ça doit m'empêcher d'appréc ier.
Euh, ça permet justement d'économiser les efforts en évitant
d'avoir à modifier le code existant... Et d'économiser des
caractères si f est appelé relativement souvent.
Franck Branjonneau wrote on 13/09/2006 19:37:Sylvain écrivait:Franck Branjonneau wrote on 13/09/2006 01:14:void f(std::vector<CPoint>& points);
Bé d'abord parce que je découvre la STL, ensuite cela m'évite de tout
changer dans un premier temps, puis cela fait des déclarations à
rallonge :o)
inline void f(std::vector<CPoint>& points) { return f(&points[0]); }
tu plaisantes ?
Non, pourquoi ?
pour rien.
je ne suis pas payé au caractère, ça doit m'empêcher d'appréc ier.
Euh, ça permet justement d'économiser les efforts en évitant
d'avoir à modifier le code existant... Et d'économiser des
caractères si f est appelé relativement souvent.
void f(std::vector<CPoint>& points);
Bé d'abord parce que je découvre la STL, ensuite cela m'évite
de tout changer dans un premier temps, puis cela fait des
déclarations à rallonge :o)
inline void f(std::vector<CPoint>& points) { return f(&points[0]); }
je ne suis pas payé au caractère, ça doit m'empêcher d'apprécier.
Euh, ça permet justement d'économiser les efforts en évitant
d'avoir à modifier le code existant... Et d'économiser des
caractères si f est appelé relativement souvent.
J'avoue ne pas comprendre ni l'un ni l'autre des critères :
-- Si on passe de T[] à std::vector<T>, on est bien en train de
modifier le code existant, non ? Et il vaut bien mieux que
le code soit homogène, et non une miche-mache imbitable des
idiomes différents, et qu'on ne sait jamais exactement ce
auquel on a à faire.
void f(std::vector<CPoint>& points);
Bé d'abord parce que je découvre la STL, ensuite cela m'évite
de tout changer dans un premier temps, puis cela fait des
déclarations à rallonge :o)
inline void f(std::vector<CPoint>& points) { return f(&points[0]); }
je ne suis pas payé au caractère, ça doit m'empêcher d'apprécier.
Euh, ça permet justement d'économiser les efforts en évitant
d'avoir à modifier le code existant... Et d'économiser des
caractères si f est appelé relativement souvent.
J'avoue ne pas comprendre ni l'un ni l'autre des critères :
-- Si on passe de T[] à std::vector<T>, on est bien en train de
modifier le code existant, non ? Et il vaut bien mieux que
le code soit homogène, et non une miche-mache imbitable des
idiomes différents, et qu'on ne sait jamais exactement ce
auquel on a à faire.
void f(std::vector<CPoint>& points);
Bé d'abord parce que je découvre la STL, ensuite cela m'évite
de tout changer dans un premier temps, puis cela fait des
déclarations à rallonge :o)
inline void f(std::vector<CPoint>& points) { return f(&points[0]); }
je ne suis pas payé au caractère, ça doit m'empêcher d'apprécier.
Euh, ça permet justement d'économiser les efforts en évitant
d'avoir à modifier le code existant... Et d'économiser des
caractères si f est appelé relativement souvent.
J'avoue ne pas comprendre ni l'un ni l'autre des critères :
-- Si on passe de T[] à std::vector<T>, on est bien en train de
modifier le code existant, non ? Et il vaut bien mieux que
le code soit homogène, et non une miche-mache imbitable des
idiomes différents, et qu'on ne sait jamais exactement ce
auquel on a à faire.
"kanze" écrivait:-- Si on passe de T[] à std::vector<T>, on est bien en train de
modifier le code existant, non ? Et il vaut bien mieux que
le code soit homogène, et non une miche-mache imbitable des
idiomes différents, et qu'on ne sait jamais exactement ce
auquel on a à faire.
Oui. Je répondais à « ne pas tout changer dans un premier
temps ».
"kanze" <kanze@gabi-soft.fr> écrivait:
-- Si on passe de T[] à std::vector<T>, on est bien en train de
modifier le code existant, non ? Et il vaut bien mieux que
le code soit homogène, et non une miche-mache imbitable des
idiomes différents, et qu'on ne sait jamais exactement ce
auquel on a à faire.
Oui. Je répondais à « ne pas tout changer dans un premier
temps ».
"kanze" écrivait:-- Si on passe de T[] à std::vector<T>, on est bien en train de
modifier le code existant, non ? Et il vaut bien mieux que
le code soit homogène, et non une miche-mache imbitable des
idiomes différents, et qu'on ne sait jamais exactement ce
auquel on a à faire.
Oui. Je répondais à « ne pas tout changer dans un premier
temps ».