J'aimerai savoir si pour supporter n'importe quel container il faut que je
fasse une surcharge par container, ou bien si en passant par les template
ça peut se faire, mais j'avoue être un peu charette là dessus...
J'aimerai savoir si pour supporter n'importe quel container il faut que je fasse une surcharge par container, ou bien si en passant par les template ça peut se faire, mais j'avoue être un peu charette là dessus...
J'aimerai savoir si pour supporter n'importe quel container il faut que je
fasse une surcharge par container, ou bien si en passant par les template
ça peut se faire, mais j'avoue être un peu charette là dessus...
J'aimerai savoir si pour supporter n'importe quel container il faut que je fasse une surcharge par container, ou bien si en passant par les template ça peut se faire, mais j'avoue être un peu charette là dessus...
qui permet de supprimer tous les pointeurs du container...
Et qui donne un comportement indéfini.
AMHA, ce n'est pas un bon exemple, pour plusieurs raisons. D'abord, formellement, il donne un comportement indéfini. Dans la pratique, ce comportement indéfini ne fait jamais de problème, et est sans importance, dans la mésure où le cible de transform est la même collection que la source. Dans d'autres cas, en revanche, on a bien une collection qui contient des pointeurs supprimés, et donc, la risque d'un comportement indéfini est élevée. Si on tient à ce que la destination et la source soient identique, on ne se sert pas de transform, mais de for_each, et delete_ptr serait plutôt :
template< typename T > struct delete_ptr { void operator()( T*& p ) { T* tmp = p ; p = NULL ; delete tmp ; } } ;
J'ai créé une fonction Purge à laquelle on passe un vecteur contenant des pointeurs, et qui fait le transform tout seul.
J'aimerai savoir si pour supporter n'importe quel container il faut que je fasse une surcharge par container, ou bien si en passant par les template ça peut se faire, mais j'avoue être un peu charette là dessus...
qui permet de supprimer tous les pointeurs du container...
Et qui donne un comportement indéfini.
AMHA, ce n'est pas un bon exemple, pour plusieurs raisons.
D'abord, formellement, il donne un comportement indéfini. Dans
la pratique, ce comportement indéfini ne fait jamais de
problème, et est sans importance, dans la mésure où le cible de
transform est la même collection que la source. Dans d'autres
cas, en revanche, on a bien une collection qui contient des
pointeurs supprimés, et donc, la risque d'un comportement
indéfini est élevée. Si on tient à ce que la destination et la
source soient identique, on ne se sert pas de transform, mais de
for_each, et delete_ptr serait plutôt :
template< typename T >
struct delete_ptr
{
void operator()( T*& p )
{
T* tmp = p ;
p = NULL ;
delete tmp ;
}
} ;
J'ai créé une fonction Purge à laquelle on passe un vecteur
contenant des pointeurs, et qui fait le transform tout seul.
J'aimerai savoir si pour supporter n'importe quel container il
faut que je fasse une surcharge par container, ou bien si en
passant par les template ça peut se faire, mais j'avoue être
un peu charette là dessus...
qui permet de supprimer tous les pointeurs du container...
Et qui donne un comportement indéfini.
AMHA, ce n'est pas un bon exemple, pour plusieurs raisons. D'abord, formellement, il donne un comportement indéfini. Dans la pratique, ce comportement indéfini ne fait jamais de problème, et est sans importance, dans la mésure où le cible de transform est la même collection que la source. Dans d'autres cas, en revanche, on a bien une collection qui contient des pointeurs supprimés, et donc, la risque d'un comportement indéfini est élevée. Si on tient à ce que la destination et la source soient identique, on ne se sert pas de transform, mais de for_each, et delete_ptr serait plutôt :
template< typename T > struct delete_ptr { void operator()( T*& p ) { T* tmp = p ; p = NULL ; delete tmp ; } } ;
J'ai créé une fonction Purge à laquelle on passe un vecteur contenant des pointeurs, et qui fait le transform tout seul.
J'aimerai savoir si pour supporter n'importe quel container il faut que je fasse une surcharge par container, ou bien si en passant par les template ça peut se faire, mais j'avoue être un peu charette là dessus...
qui permet de supprimer tous les pointeurs du container...
Et qui donne un comportement indéfini.
AMHA, ce n'est pas un bon exemple, pour plusieurs raisons. D'abord, formellement, il donne un comportement indéfini. Dans la pratique, ce comportement indéfini ne fait jamais de problème, et est sans importance, dans la mésure où le cible de transform est la même collection que la source. Dans d'autres cas, en revanche, on a bien une collection qui contient des pointeurs supprimés, et donc, la risque d'un comportement indéfini est élevée. Si on tient à ce que la destination et la source soient identique, on ne se sert pas de transform, mais de for_each, et delete_ptr serait plutôt :
template< typename T > struct delete_ptr { void operator()( T*& p ) { T* tmp = p ; p = NULL ; delete tmp ; } } ;
J'ai créé une fonction Purge à laquelle on passe un vecteur contenant des pointeurs, et qui fait le transform tout seul.
J'aimerai savoir si pour supporter n'importe quel container il faut que je fasse une surcharge par container, ou bien si en passant par les template ça peut se faire, mais j'avoue être un peu charette là dessus...
qui permet de supprimer tous les pointeurs du container...
Et qui donne un comportement indéfini.
AMHA, ce n'est pas un bon exemple, pour plusieurs raisons.
D'abord, formellement, il donne un comportement indéfini. Dans
la pratique, ce comportement indéfini ne fait jamais de
problème, et est sans importance, dans la mésure où le cible de
transform est la même collection que la source. Dans d'autres
cas, en revanche, on a bien une collection qui contient des
pointeurs supprimés, et donc, la risque d'un comportement
indéfini est élevée. Si on tient à ce que la destination et la
source soient identique, on ne se sert pas de transform, mais de
for_each, et delete_ptr serait plutôt :
template< typename T >
struct delete_ptr
{
void operator()( T*& p )
{
T* tmp = p ;
p = NULL ;
delete tmp ;
}
} ;
J'ai créé une fonction Purge à laquelle on passe un vecteur
contenant des pointeurs, et qui fait le transform tout seul.
J'aimerai savoir si pour supporter n'importe quel container il
faut que je fasse une surcharge par container, ou bien si en
passant par les template ça peut se faire, mais j'avoue être
un peu charette là dessus...
qui permet de supprimer tous les pointeurs du container...
Et qui donne un comportement indéfini.
AMHA, ce n'est pas un bon exemple, pour plusieurs raisons. D'abord, formellement, il donne un comportement indéfini. Dans la pratique, ce comportement indéfini ne fait jamais de problème, et est sans importance, dans la mésure où le cible de transform est la même collection que la source. Dans d'autres cas, en revanche, on a bien une collection qui contient des pointeurs supprimés, et donc, la risque d'un comportement indéfini est élevée. Si on tient à ce que la destination et la source soient identique, on ne se sert pas de transform, mais de for_each, et delete_ptr serait plutôt :
template< typename T > struct delete_ptr { void operator()( T*& p ) { T* tmp = p ; p = NULL ; delete tmp ; } } ;
J'ai créé une fonction Purge à laquelle on passe un vecteur contenant des pointeurs, et qui fait le transform tout seul.
J'aimerai savoir si pour supporter n'importe quel container il faut que je fasse une surcharge par container, ou bien si en passant par les template ça peut se faire, mais j'avoue être un peu charette là dessus...
(Enfin, c'est ce que j'aimerais faire. Pour l'instant, je suis obligé à me servir d'un compilateur qui ne supporte pas Boost.)
-- James Kanze GABI Software http://www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Michael
Pourais tu m'expliquer ce code s'il te plait, je ne comprends pas tout:
template< typename T > struct delete_ptr { void operator()( T*& p ) { T* tmp = p ; p = NULL ; delete tmp ; } } ;
Là il s'agit d'un foncteur, mais pourquoi faire un delete d'un temporaire?
template< typename Container > void purge( Container& c ) { typedef Container::value_type Ptr ; Ici je ne connais pas, mais je suppose que Container::value_type correspond
au type d'objets contenus par Container??? (ici un pointeur?)
BOOST_STATIC_ASSERT( boost::is_pointer< Ptr >::value ) ; Je ne suis pas familier des asserts, mais je suppose que c'est pour
vérifier que le contenu du container est bien un pointeur
Pourquoi enlever le pointeur ici? A quoi correspond ::type?
}
Merci d'avance!
Pourais tu m'expliquer ce code s'il te plait, je ne comprends pas tout:
template< typename T >
struct delete_ptr
{
void operator()( T*& p )
{
T* tmp = p ;
p = NULL ;
delete tmp ;
}
} ;
Là il s'agit d'un foncteur, mais pourquoi faire un delete d'un temporaire?
template< typename Container >
void
purge( Container& c )
{
typedef Container::value_type Ptr ;
Ici je ne connais pas, mais je suppose que Container::value_type correspond
au type d'objets contenus par Container??? (ici un pointeur?)
BOOST_STATIC_ASSERT( boost::is_pointer< Ptr >::value ) ;
Je ne suis pas familier des asserts, mais je suppose que c'est pour
vérifier que le contenu du container est bien un pointeur
Pourais tu m'expliquer ce code s'il te plait, je ne comprends pas tout:
template< typename T > struct delete_ptr { void operator()( T*& p ) { T* tmp = p ; p = NULL ; delete tmp ; } } ;
Là il s'agit d'un foncteur, mais pourquoi faire un delete d'un temporaire?
template< typename Container > void purge( Container& c ) { typedef Container::value_type Ptr ; Ici je ne connais pas, mais je suppose que Container::value_type correspond
au type d'objets contenus par Container??? (ici un pointeur?)
BOOST_STATIC_ASSERT( boost::is_pointer< Ptr >::value ) ; Je ne suis pas familier des asserts, mais je suppose que c'est pour
vérifier que le contenu du container est bien un pointeur
Pourquoi enlever le pointeur ici? A quoi correspond ::type?
}
Merci d'avance!
kanze
Michael wrote:
Pourais tu m'expliquer ce code s'il te plait, je ne comprends pas tout:
template< typename T > struct delete_ptr { void operator()( T*& p )
(Il faudrait y ajouter un const que j' ai oublie.)
{ T* tmp = p ; p = NULL ; delete tmp ; } } ;
Là il s'agit d'un foncteur, mais pourquoi faire un delete d'un temporaire?
Parce que techniquement, faire un delete sur un pointeur qui est contenu dans une collection standard a un comportement indéfini. Donc, on met le pointeur dans un temporaire, on remplace avec null dans la collection, et seulement alors on fait le delete.
Ici je ne connais pas, mais je suppose que Container::value_type correspond au type d'objets contenus par Container??? (ici un pointeur?)
Tout à fait. Je dirais que l'utilisation de tous ces typedef's, c'est la véritable innovation de la STL. À apprendre -- ça t'étonnerait à quel point c'est utile.
Je ne suis pas familier des asserts, mais je suppose que c'est pour vérifier que le contenu du container est bien un pointeur
C'est du Boost (aussi à apprendre). BOOST_STATIC_ASSERT, c'est un assert qui déclenche lors de la compilation. C-à-d ici is Ptr n'est pas un pointeur, on aurait une erreur de compilation.
Pourquoi enlever le pointeur ici? A quoi correspond ::type?
Encore : boost::remove_ptr est une classe générique avec un typedef d'un type qui s'appelle type. Si la type d'instanciation est un pointeur, le typedef est le type sans le pointeur.
}
Écrire des choses comme remove_pointer, etc., n'est pas trivial. Il y a beaucoup de chose à apprendre avant. Les utiliser, en revanche, n'est pas si compliquer, et vaut la peine, même si on n'est pas très avancé. (À vrai dire, je ne crois pas que remove_pointer en soi soit si difficile. Mais l'ensemble dont il fait partie utilise des techniques qu'il faut bien qualifier d'avancées.)
-- James Kanze GABI Software http://www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Michael wrote:
Pourais tu m'expliquer ce code s'il te plait, je ne comprends
pas tout:
template< typename T >
struct delete_ptr
{
void operator()( T*& p )
(Il faudrait y ajouter un const que j' ai oublie.)
{
T* tmp = p ;
p = NULL ;
delete tmp ;
}
} ;
Là il s'agit d'un foncteur, mais pourquoi faire un delete d'un
temporaire?
Parce que techniquement, faire un delete sur un pointeur qui est
contenu dans une collection standard a un comportement
indéfini. Donc, on met le pointeur dans un temporaire, on
remplace avec null dans la collection, et seulement alors on
fait le delete.
Ici je ne connais pas, mais je suppose que
Container::value_type correspond au type d'objets contenus par
Container??? (ici un pointeur?)
Tout à fait. Je dirais que l'utilisation de tous ces typedef's,
c'est la véritable innovation de la STL. À apprendre -- ça
t'étonnerait à quel point c'est utile.
Je ne suis pas familier des asserts, mais je suppose que c'est
pour vérifier que le contenu du container est bien un pointeur
C'est du Boost (aussi à apprendre). BOOST_STATIC_ASSERT, c'est
un assert qui déclenche lors de la compilation. C-à-d ici is Ptr
n'est pas un pointeur, on aurait une erreur de compilation.
Pourquoi enlever le pointeur ici? A quoi correspond ::type?
Encore : boost::remove_ptr est une classe générique avec un
typedef d'un type qui s'appelle type. Si la type d'instanciation
est un pointeur, le typedef est le type sans le pointeur.
}
Écrire des choses comme remove_pointer, etc., n'est pas
trivial. Il y a beaucoup de chose à apprendre avant. Les
utiliser, en revanche, n'est pas si compliquer, et vaut la
peine, même si on n'est pas très avancé. (À vrai dire, je ne
crois pas que remove_pointer en soi soit si difficile. Mais
l'ensemble dont il fait partie utilise des techniques qu'il faut
bien qualifier d'avancées.)
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Pourais tu m'expliquer ce code s'il te plait, je ne comprends pas tout:
template< typename T > struct delete_ptr { void operator()( T*& p )
(Il faudrait y ajouter un const que j' ai oublie.)
{ T* tmp = p ; p = NULL ; delete tmp ; } } ;
Là il s'agit d'un foncteur, mais pourquoi faire un delete d'un temporaire?
Parce que techniquement, faire un delete sur un pointeur qui est contenu dans une collection standard a un comportement indéfini. Donc, on met le pointeur dans un temporaire, on remplace avec null dans la collection, et seulement alors on fait le delete.
Ici je ne connais pas, mais je suppose que Container::value_type correspond au type d'objets contenus par Container??? (ici un pointeur?)
Tout à fait. Je dirais que l'utilisation de tous ces typedef's, c'est la véritable innovation de la STL. À apprendre -- ça t'étonnerait à quel point c'est utile.
Je ne suis pas familier des asserts, mais je suppose que c'est pour vérifier que le contenu du container est bien un pointeur
C'est du Boost (aussi à apprendre). BOOST_STATIC_ASSERT, c'est un assert qui déclenche lors de la compilation. C-à-d ici is Ptr n'est pas un pointeur, on aurait une erreur de compilation.
Pourquoi enlever le pointeur ici? A quoi correspond ::type?
Encore : boost::remove_ptr est une classe générique avec un typedef d'un type qui s'appelle type. Si la type d'instanciation est un pointeur, le typedef est le type sans le pointeur.
}
Écrire des choses comme remove_pointer, etc., n'est pas trivial. Il y a beaucoup de chose à apprendre avant. Les utiliser, en revanche, n'est pas si compliquer, et vaut la peine, même si on n'est pas très avancé. (À vrai dire, je ne crois pas que remove_pointer en soi soit si difficile. Mais l'ensemble dont il fait partie utilise des techniques qu'il faut bien qualifier d'avancées.)
-- James Kanze GABI Software http://www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Michael
Merci pour toutes ces explications... Néanmoins il y a encore quelque chose que je ne comprends pas:
Pourquoi passer une référence de pointeur à delete_ptr et pas le pointeur directement? Le comportement indéfini auquel tu fais allusion en est-il la seule explication?
Merci pour toutes ces explications... Néanmoins il y a encore quelque chose
que je ne comprends pas:
Pourquoi passer une référence de pointeur à delete_ptr et pas le pointeur
directement? Le comportement indéfini auquel tu fais allusion en est-il la
seule explication?
Merci pour toutes ces explications... Néanmoins il y a encore quelque chose que je ne comprends pas:
Pourquoi passer une référence de pointeur à delete_ptr et pas le pointeur directement? Le comportement indéfini auquel tu fais allusion en est-il la seule explication?
Michael
xavier wrote in news:41ecee27$0$7832$:
Michael a dit le 18/01/2005 11:47:
Pourquoi passer une référence de pointeur à delete_ptr et pas le pointeur directement? Le comportement indéfini auquel tu fais allusion en est-il la seule explication?
Pour pouvoir modifier la valeur du pointeur dans le conteneur, il faut le passer par référence.
Alors pourquoi mon premier exemple tiré du bouquin compilait sans problèmes?
xavier <xtrochu@yahoo.com> wrote in
news:41ecee27$0$7832$636a15ce@news.free.fr:
Michael a dit le 18/01/2005 11:47:
Pourquoi passer une référence de pointeur à delete_ptr et pas le
pointeur directement? Le comportement indéfini auquel tu fais
allusion en est-il la seule explication?
Pour pouvoir modifier la valeur du pointeur dans le conteneur, il faut
le passer par référence.
Alors pourquoi mon premier exemple tiré du bouquin compilait sans
problèmes?
Pourquoi passer une référence de pointeur à delete_ptr et pas le pointeur directement? Le comportement indéfini auquel tu fais allusion en est-il la seule explication?
Pour pouvoir modifier la valeur du pointeur dans le conteneur, il faut le passer par référence.
Alors pourquoi mon premier exemple tiré du bouquin compilait sans problèmes?
xavier
Michael a dit le 18/01/2005 11:47:
Pourquoi passer une référence de pointeur à delete_ptr et pas le pointeur directement? Le comportement indéfini auquel tu fais allusion en est-il la seule explication?
Pour pouvoir modifier la valeur du pointeur dans le conteneur, il faut le passer par référence.
Par contre, j'aimerais savoir en quoi un pointeur invalide dans un conteneur est un comportement indéfini. A priori, je pensais que le conteneur lui-même ne pouvait manipuler que les pointeurs, et pas les déréférencer... La manipulation de pointeur invalide est-elle un comportement indéfini, tout simplement, ou y a-t-il une raison plus complexe ?
xavier
Michael a dit le 18/01/2005 11:47:
Pourquoi passer une référence de pointeur à delete_ptr et pas le pointeur
directement? Le comportement indéfini auquel tu fais allusion en est-il la
seule explication?
Pour pouvoir modifier la valeur du pointeur dans le conteneur, il faut
le passer par référence.
Par contre, j'aimerais savoir en quoi un pointeur invalide dans un
conteneur est un comportement indéfini. A priori, je pensais que le
conteneur lui-même ne pouvait manipuler que les pointeurs, et pas les
déréférencer... La manipulation de pointeur invalide est-elle un
comportement indéfini, tout simplement, ou y a-t-il une raison plus
complexe ?
Pourquoi passer une référence de pointeur à delete_ptr et pas le pointeur directement? Le comportement indéfini auquel tu fais allusion en est-il la seule explication?
Pour pouvoir modifier la valeur du pointeur dans le conteneur, il faut le passer par référence.
Par contre, j'aimerais savoir en quoi un pointeur invalide dans un conteneur est un comportement indéfini. A priori, je pensais que le conteneur lui-même ne pouvait manipuler que les pointeurs, et pas les déréférencer... La manipulation de pointeur invalide est-elle un comportement indéfini, tout simplement, ou y a-t-il une raison plus complexe ?
xavier
Michael
OK, c'est très clair maintenant...
Du coup j'en profite pour poser une autre question :-D
*dest++ = operation(*it);
Dans l'ordre, c'est affectation puis incrémentation?
J'imagine que c'est l'inverse si on choisit une pré-incrémentation?
OK, c'est très clair maintenant...
Du coup j'en profite pour poser une autre question :-D
*dest++ = operation(*it);
Dans l'ordre, c'est affectation puis incrémentation?
J'imagine que c'est l'inverse si on choisit une pré-incrémentation?