Je suis surpris et déçu de constater que plusieurs pointeurs
intelligents (auto_ptr, boost) ont leur opérateur d'indirection défini
ainsi:
T* operator->() const;
Je supose qu'il y a une bonne raison à celà,
Je suis surpris et déçu de constater que plusieurs pointeurs
intelligents (auto_ptr, boost) ont leur opérateur d'indirection défini
ainsi:
T* operator->() const;
Je supose qu'il y a une bonne raison à celà,
Je suis surpris et déçu de constater que plusieurs pointeurs
intelligents (auto_ptr, boost) ont leur opérateur d'indirection défini
ainsi:
T* operator->() const;
Je supose qu'il y a une bonne raison à celà,
Je suis surpris et déçu de constater que plusieurs pointeurs
intelligents (auto_ptr, boost) ont leur opérateur
d'indirection défini ainsi:
T* operator->() const;
alors que je me serais attendu à:
T* operator->();
const T* operator->() const;
ce qui permet d'avoir une erreur de compilation dans l'exemple
qui suit:
class A
{
public:
void f1() const {}
void f2() {}
};
const auto_ptr<A> p( new A ); // <- const
p->f1();
p->f2(); // erreur de compilation attendue mais...
Du coup il faut passer par un
auto_ptr<const A>
qui ne peut pas être implicitement converti depuis un
auto_ptr<A>
:/
(cela dit ça marche avec boost, dans une certaine mesure).
Je supose qu'il y a une bonne raison à celà, mais je ne la
devine pas. La connaissez-vous ?
Je suis surpris et déçu de constater que plusieurs pointeurs
intelligents (auto_ptr, boost) ont leur opérateur
d'indirection défini ainsi:
T* operator->() const;
alors que je me serais attendu à:
T* operator->();
const T* operator->() const;
ce qui permet d'avoir une erreur de compilation dans l'exemple
qui suit:
class A
{
public:
void f1() const {}
void f2() {}
};
const auto_ptr<A> p( new A ); // <- const
p->f1();
p->f2(); // erreur de compilation attendue mais...
Du coup il faut passer par un
auto_ptr<const A>
qui ne peut pas être implicitement converti depuis un
auto_ptr<A>
:/
(cela dit ça marche avec boost, dans une certaine mesure).
Je supose qu'il y a une bonne raison à celà, mais je ne la
devine pas. La connaissez-vous ?
Je suis surpris et déçu de constater que plusieurs pointeurs
intelligents (auto_ptr, boost) ont leur opérateur
d'indirection défini ainsi:
T* operator->() const;
alors que je me serais attendu à:
T* operator->();
const T* operator->() const;
ce qui permet d'avoir une erreur de compilation dans l'exemple
qui suit:
class A
{
public:
void f1() const {}
void f2() {}
};
const auto_ptr<A> p( new A ); // <- const
p->f1();
p->f2(); // erreur de compilation attendue mais...
Du coup il faut passer par un
auto_ptr<const A>
qui ne peut pas être implicitement converti depuis un
auto_ptr<A>
:/
(cela dit ça marche avec boost, dans une certaine mesure).
Je supose qu'il y a une bonne raison à celà, mais je ne la
devine pas. La connaissez-vous ?
On Wed, 26 Apr 2006 18:09:05 +0200, Aurelien Regat-Barrel
:Je suis surpris et déçu de constater que plusieurs pointeurs
intelligents (auto_ptr, boost) ont leur opérateur d'indirection défini
ainsi:
T* operator->() const;Je supose qu'il y a une bonne raison à celà,
Une raison toute simple : un pointeur intelligent a une interface
aussi proche que possible de celle d'un pointeur "brut", pour pouvoir
facilement les remplacer.
Ainsi, un auto_ptr<T> fonctionne de la même façon qu'un T*.
De même, on a les correspondances :
auto_ptr<T const> <==> T const *
auto_ptr<T> const <==> T * const
auto_ptr<T const> const <==> T const * const
void f (int* const ptr)
{
int x= 0;
//ptr= &x; // Marche pas, car le pointeur est const
*ptr= x; // Fonctionne, car la variable pointée est non-const
}
Si tu remplaces int* par auto_ptr<int>, ça fonctionne de la même
façon.
On Wed, 26 Apr 2006 18:09:05 +0200, Aurelien Regat-Barrel
<nospam.aregatba@yahoo.fr>:
Je suis surpris et déçu de constater que plusieurs pointeurs
intelligents (auto_ptr, boost) ont leur opérateur d'indirection défini
ainsi:
T* operator->() const;
Je supose qu'il y a une bonne raison à celà,
Une raison toute simple : un pointeur intelligent a une interface
aussi proche que possible de celle d'un pointeur "brut", pour pouvoir
facilement les remplacer.
Ainsi, un auto_ptr<T> fonctionne de la même façon qu'un T*.
De même, on a les correspondances :
auto_ptr<T const> <==> T const *
auto_ptr<T> const <==> T * const
auto_ptr<T const> const <==> T const * const
void f (int* const ptr)
{
int x= 0;
//ptr= &x; // Marche pas, car le pointeur est const
*ptr= x; // Fonctionne, car la variable pointée est non-const
}
Si tu remplaces int* par auto_ptr<int>, ça fonctionne de la même
façon.
On Wed, 26 Apr 2006 18:09:05 +0200, Aurelien Regat-Barrel
:Je suis surpris et déçu de constater que plusieurs pointeurs
intelligents (auto_ptr, boost) ont leur opérateur d'indirection défini
ainsi:
T* operator->() const;Je supose qu'il y a une bonne raison à celà,
Une raison toute simple : un pointeur intelligent a une interface
aussi proche que possible de celle d'un pointeur "brut", pour pouvoir
facilement les remplacer.
Ainsi, un auto_ptr<T> fonctionne de la même façon qu'un T*.
De même, on a les correspondances :
auto_ptr<T const> <==> T const *
auto_ptr<T> const <==> T * const
auto_ptr<T const> const <==> T const * const
void f (int* const ptr)
{
int x= 0;
//ptr= &x; // Marche pas, car le pointeur est const
*ptr= x; // Fonctionne, car la variable pointée est non-const
}
Si tu remplaces int* par auto_ptr<int>, ça fonctionne de la même
façon.
const auto_ptr<A> p( new A ); // <- const
p->f1();
p->f2(); // erreur de compilation attendue mais...
Mais tu ne veux pas d'erreur de compilation ici.
Du coup il faut passer par un
auto_ptr<const A>
qui ne peut pas être implicitement converti depuis un
auto_ptr<A>
Ça dépend où et comment. Les suivants marchent bien :
std::auto_ptr< A > pa( new A ) ;
std::auto_ptr< A const > pca( pa ) ;
pca = pa ;
Appeler une fonction qui prend un std::auto_ptr< A const > ou un
std::auto_ptr< A const > const&, en revanche, non.:/
(cela dit ça marche avec boost, dans une certaine mesure).
Pas de problème avec shared_ptr, y compris avec les appels de
fonctions.
Je supose qu'il y a une bonne raison à celà, mais je ne la
devine pas. La connaissez-vous ?
La raison pourquoi la conversion implicite lors l'appel de
fonction avec auto_ptr ne marche pas, c'est lié au fait qu'on
(c-à-d ici, la délégation brittanique) a insisté que
std::vector< std::auto_ptr > provoque une erreur à la
compilation, plutôt que d'être simplement un comportement
indéfini. Ce qui fait que la sémantique d'auto_ptr est parfois
un peu bizarre. Dans la pratique, en revanche, je ne ai jamais
trouvé que c'est un problème -- si je passe un auto_ptr à une
fonction, l'objet qu'il désigne ne m'est plus accessible ; ça
m'est donc égal qu'il soit modifié ou non. Du coup, je crois que
je ne me suis jamais servi d'un auto_ptr à un const. Ce n'est
pas le cas de shared_ptr, évidemment. Mais shared_ptr n'a pas
besoin de tous ces bricolages pour provoquer une erreur dans
std::vector< std::shared_ptr >. Un vector des shared_ptr est
tout à fait légal, et a un comportement défini
const auto_ptr<A> p( new A ); // <- const
p->f1();
p->f2(); // erreur de compilation attendue mais...
Mais tu ne veux pas d'erreur de compilation ici.
Du coup il faut passer par un
auto_ptr<const A>
qui ne peut pas être implicitement converti depuis un
auto_ptr<A>
Ça dépend où et comment. Les suivants marchent bien :
std::auto_ptr< A > pa( new A ) ;
std::auto_ptr< A const > pca( pa ) ;
pca = pa ;
Appeler une fonction qui prend un std::auto_ptr< A const > ou un
std::auto_ptr< A const > const&, en revanche, non.
:/
(cela dit ça marche avec boost, dans une certaine mesure).
Pas de problème avec shared_ptr, y compris avec les appels de
fonctions.
Je supose qu'il y a une bonne raison à celà, mais je ne la
devine pas. La connaissez-vous ?
La raison pourquoi la conversion implicite lors l'appel de
fonction avec auto_ptr ne marche pas, c'est lié au fait qu'on
(c-à-d ici, la délégation brittanique) a insisté que
std::vector< std::auto_ptr > provoque une erreur à la
compilation, plutôt que d'être simplement un comportement
indéfini. Ce qui fait que la sémantique d'auto_ptr est parfois
un peu bizarre. Dans la pratique, en revanche, je ne ai jamais
trouvé que c'est un problème -- si je passe un auto_ptr à une
fonction, l'objet qu'il désigne ne m'est plus accessible ; ça
m'est donc égal qu'il soit modifié ou non. Du coup, je crois que
je ne me suis jamais servi d'un auto_ptr à un const. Ce n'est
pas le cas de shared_ptr, évidemment. Mais shared_ptr n'a pas
besoin de tous ces bricolages pour provoquer une erreur dans
std::vector< std::shared_ptr >. Un vector des shared_ptr est
tout à fait légal, et a un comportement défini
const auto_ptr<A> p( new A ); // <- const
p->f1();
p->f2(); // erreur de compilation attendue mais...
Mais tu ne veux pas d'erreur de compilation ici.
Du coup il faut passer par un
auto_ptr<const A>
qui ne peut pas être implicitement converti depuis un
auto_ptr<A>
Ça dépend où et comment. Les suivants marchent bien :
std::auto_ptr< A > pa( new A ) ;
std::auto_ptr< A const > pca( pa ) ;
pca = pa ;
Appeler une fonction qui prend un std::auto_ptr< A const > ou un
std::auto_ptr< A const > const&, en revanche, non.:/
(cela dit ça marche avec boost, dans une certaine mesure).
Pas de problème avec shared_ptr, y compris avec les appels de
fonctions.
Je supose qu'il y a une bonne raison à celà, mais je ne la
devine pas. La connaissez-vous ?
La raison pourquoi la conversion implicite lors l'appel de
fonction avec auto_ptr ne marche pas, c'est lié au fait qu'on
(c-à-d ici, la délégation brittanique) a insisté que
std::vector< std::auto_ptr > provoque une erreur à la
compilation, plutôt que d'être simplement un comportement
indéfini. Ce qui fait que la sémantique d'auto_ptr est parfois
un peu bizarre. Dans la pratique, en revanche, je ne ai jamais
trouvé que c'est un problème -- si je passe un auto_ptr à une
fonction, l'objet qu'il désigne ne m'est plus accessible ; ça
m'est donc égal qu'il soit modifié ou non. Du coup, je crois que
je ne me suis jamais servi d'un auto_ptr à un const. Ce n'est
pas le cas de shared_ptr, évidemment. Mais shared_ptr n'a pas
besoin de tous ces bricolages pour provoquer une erreur dans
std::vector< std::shared_ptr >. Un vector des shared_ptr est
tout à fait légal, et a un comportement défini
On Wed, 26 Apr 2006 18:09:05 +0200, Aurelien Regat-Barrel
:Je suis surpris et déçu de constater que plusieurs pointeurs
intelligents (auto_ptr, boost) ont leur opérateur
d'indirection défini ainsi:
T* operator->() const;
Je supose qu'il y a une bonne raison à celà,
Une raison toute simple : un pointeur intelligent a une
interface aussi proche que possible de celle d'un pointeur
"brut", pour pouvoir facilement les remplacer.
Ainsi, un auto_ptr<T> fonctionne de la même façon qu'un T*.
De même, on a les correspondances :
auto_ptr<T const> <==> T const *
auto_ptr<T> const <==> T * const
auto_ptr<T const> const <==> T const * const
void f (int* const ptr)
{
int x= 0;
//ptr= &x; // Marche pas, car le pointeur est const
*ptr= x; // Fonctionne, car la variable pointée est non-const
}
Si tu remplaces int* par auto_ptr<int>, ça fonctionne de la
même façon.
Moui, je comprends. En fait c'est le même "piège" que typdef:
typedef A* APtr;
const APtr ptr1; // peut modifier *ptr1
const A* ptr2;
Cela dit, est-ce que tu serais choqué par un pointeur
intelligent qui se comporterait comme je le souhaite ?
On Wed, 26 Apr 2006 18:09:05 +0200, Aurelien Regat-Barrel
<nospam.aregatba@yahoo.fr>:
Je suis surpris et déçu de constater que plusieurs pointeurs
intelligents (auto_ptr, boost) ont leur opérateur
d'indirection défini ainsi:
T* operator->() const;
Je supose qu'il y a une bonne raison à celà,
Une raison toute simple : un pointeur intelligent a une
interface aussi proche que possible de celle d'un pointeur
"brut", pour pouvoir facilement les remplacer.
Ainsi, un auto_ptr<T> fonctionne de la même façon qu'un T*.
De même, on a les correspondances :
auto_ptr<T const> <==> T const *
auto_ptr<T> const <==> T * const
auto_ptr<T const> const <==> T const * const
void f (int* const ptr)
{
int x= 0;
//ptr= &x; // Marche pas, car le pointeur est const
*ptr= x; // Fonctionne, car la variable pointée est non-const
}
Si tu remplaces int* par auto_ptr<int>, ça fonctionne de la
même façon.
Moui, je comprends. En fait c'est le même "piège" que typdef:
typedef A* APtr;
const APtr ptr1; // peut modifier *ptr1
const A* ptr2;
Cela dit, est-ce que tu serais choqué par un pointeur
intelligent qui se comporterait comme je le souhaite ?
On Wed, 26 Apr 2006 18:09:05 +0200, Aurelien Regat-Barrel
:Je suis surpris et déçu de constater que plusieurs pointeurs
intelligents (auto_ptr, boost) ont leur opérateur
d'indirection défini ainsi:
T* operator->() const;
Je supose qu'il y a une bonne raison à celà,
Une raison toute simple : un pointeur intelligent a une
interface aussi proche que possible de celle d'un pointeur
"brut", pour pouvoir facilement les remplacer.
Ainsi, un auto_ptr<T> fonctionne de la même façon qu'un T*.
De même, on a les correspondances :
auto_ptr<T const> <==> T const *
auto_ptr<T> const <==> T * const
auto_ptr<T const> const <==> T const * const
void f (int* const ptr)
{
int x= 0;
//ptr= &x; // Marche pas, car le pointeur est const
*ptr= x; // Fonctionne, car la variable pointée est non-const
}
Si tu remplaces int* par auto_ptr<int>, ça fonctionne de la
même façon.
Moui, je comprends. En fait c'est le même "piège" que typdef:
typedef A* APtr;
const APtr ptr1; // peut modifier *ptr1
const A* ptr2;
Cela dit, est-ce que tu serais choqué par un pointeur
intelligent qui se comporterait comme je le souhaite ?
const auto_ptr<A> p( new A ); // <- const
p->f1();
p->f2(); // erreur de compilation attendue mais...
Mais tu ne veux pas d'erreur de compilation ici.
En répondant à Fabien je l'ai réalisé.Du coup il faut passer par un
auto_ptr<const A>
qui ne peut pas être implicitement converti depuis un
auto_ptr<A>
Ça dépend où et comment. Les suivants marchent bien :
std::auto_ptr< A > pa( new A ) ;
std::auto_ptr< A const > pca( pa ) ;
pca = pa ;
Appeler une fonction qui prend un std::auto_ptr< A const >
ou un std::auto_ptr< A const > const&, en revanche, non.:/
(cela dit ça marche avec boost, dans une certaine mesure).
Pas de problème avec shared_ptr, y compris avec les appels
de fonctions.
boost::shared_ptr faisait mon bonheur jusqu'à hier:
typedef boost::shared_ptr<A> APtr;
typedef std::vector<APtr> AVect;
typedef boost::shared_ptr<A const> AConstPtr;
typedef std::vector<AConstPtr> AConstVect;
en fait c'est std::vector le coupable:
void Test1( AConstPtr );
void Test2( AConstVect );
APtr ptr( new A );
AVect v;
v.push_back( ptr );
Test1( ptr ); // ok
Test2( v ); // pas content
du coup, j'hésite à utiliser const dans mes pointeurs
intelligents, et donc il perd son utilité au sein même de mes
classes :-/
const auto_ptr<A> p( new A ); // <- const
p->f1();
p->f2(); // erreur de compilation attendue mais...
Mais tu ne veux pas d'erreur de compilation ici.
En répondant à Fabien je l'ai réalisé.
Du coup il faut passer par un
auto_ptr<const A>
qui ne peut pas être implicitement converti depuis un
auto_ptr<A>
Ça dépend où et comment. Les suivants marchent bien :
std::auto_ptr< A > pa( new A ) ;
std::auto_ptr< A const > pca( pa ) ;
pca = pa ;
Appeler une fonction qui prend un std::auto_ptr< A const >
ou un std::auto_ptr< A const > const&, en revanche, non.
:/
(cela dit ça marche avec boost, dans une certaine mesure).
Pas de problème avec shared_ptr, y compris avec les appels
de fonctions.
boost::shared_ptr faisait mon bonheur jusqu'à hier:
typedef boost::shared_ptr<A> APtr;
typedef std::vector<APtr> AVect;
typedef boost::shared_ptr<A const> AConstPtr;
typedef std::vector<AConstPtr> AConstVect;
en fait c'est std::vector le coupable:
void Test1( AConstPtr );
void Test2( AConstVect );
APtr ptr( new A );
AVect v;
v.push_back( ptr );
Test1( ptr ); // ok
Test2( v ); // pas content
du coup, j'hésite à utiliser const dans mes pointeurs
intelligents, et donc il perd son utilité au sein même de mes
classes :-/
const auto_ptr<A> p( new A ); // <- const
p->f1();
p->f2(); // erreur de compilation attendue mais...
Mais tu ne veux pas d'erreur de compilation ici.
En répondant à Fabien je l'ai réalisé.Du coup il faut passer par un
auto_ptr<const A>
qui ne peut pas être implicitement converti depuis un
auto_ptr<A>
Ça dépend où et comment. Les suivants marchent bien :
std::auto_ptr< A > pa( new A ) ;
std::auto_ptr< A const > pca( pa ) ;
pca = pa ;
Appeler une fonction qui prend un std::auto_ptr< A const >
ou un std::auto_ptr< A const > const&, en revanche, non.:/
(cela dit ça marche avec boost, dans une certaine mesure).
Pas de problème avec shared_ptr, y compris avec les appels
de fonctions.
boost::shared_ptr faisait mon bonheur jusqu'à hier:
typedef boost::shared_ptr<A> APtr;
typedef std::vector<APtr> AVect;
typedef boost::shared_ptr<A const> AConstPtr;
typedef std::vector<AConstPtr> AConstVect;
en fait c'est std::vector le coupable:
void Test1( AConstPtr );
void Test2( AConstVect );
APtr ptr( new A );
AVect v;
v.push_back( ptr );
Test1( ptr ); // ok
Test2( v ); // pas content
du coup, j'hésite à utiliser const dans mes pointeurs
intelligents, et donc il perd son utilité au sein même de mes
classes :-/
Cela dit, est-ce que tu serais choqué par un pointeur intelligent qui se
comporterait comme je le souhaite ?
Cela dit, est-ce que tu serais choqué par un pointeur intelligent qui se
comporterait comme je le souhaite ?
Cela dit, est-ce que tu serais choqué par un pointeur intelligent qui se
comporterait comme je le souhaite ?
Moui, je comprends. En fait c'est le même "piège" que typdef:typedef A* APtr;
const APtr ptr1; // peut modifier *ptr1
const A* ptr2;
Sauf que ce n'est pas réelement un piège, à mon avis. Si on
considère ce que signifie typedef -- ce n'est pas qu'un macro.
Mais comme j'ai dit dans ma réponse, si tu écrivais le const
derrière ce qu'il modifie, même en le considérant comme un
macro, tu n'auras pas de surprise. Ici, en tout cas.
Cela dit, est-ce que tu serais choqué par un pointeur
intelligent qui se comporterait comme je le souhaite ?
Assez, oui. Un pointeur ne se modifie pas si on modifie le
pointé ; c'est donc normal que le const du pointeur n'affecte
pas l'accéssibilité de l'objet.
Moui, je comprends. En fait c'est le même "piège" que typdef:
typedef A* APtr;
const APtr ptr1; // peut modifier *ptr1
const A* ptr2;
Sauf que ce n'est pas réelement un piège, à mon avis. Si on
considère ce que signifie typedef -- ce n'est pas qu'un macro.
Mais comme j'ai dit dans ma réponse, si tu écrivais le const
derrière ce qu'il modifie, même en le considérant comme un
macro, tu n'auras pas de surprise. Ici, en tout cas.
Cela dit, est-ce que tu serais choqué par un pointeur
intelligent qui se comporterait comme je le souhaite ?
Assez, oui. Un pointeur ne se modifie pas si on modifie le
pointé ; c'est donc normal que le const du pointeur n'affecte
pas l'accéssibilité de l'objet.
Moui, je comprends. En fait c'est le même "piège" que typdef:typedef A* APtr;
const APtr ptr1; // peut modifier *ptr1
const A* ptr2;
Sauf que ce n'est pas réelement un piège, à mon avis. Si on
considère ce que signifie typedef -- ce n'est pas qu'un macro.
Mais comme j'ai dit dans ma réponse, si tu écrivais le const
derrière ce qu'il modifie, même en le considérant comme un
macro, tu n'auras pas de surprise. Ici, en tout cas.
Cela dit, est-ce que tu serais choqué par un pointeur
intelligent qui se comporterait comme je le souhaite ?
Assez, oui. Un pointeur ne se modifie pas si on modifie le
pointé ; c'est donc normal que le const du pointeur n'affecte
pas l'accéssibilité de l'objet.
Cela dit, est-ce que tu serais choqué par un pointeur intelligent qui se
comporterait comme je le souhaite ?
Tu peux faire une classe qui se comporte comme tu le souhaites.
L'appeler "pointeur" me choquerait effectivement.
Cela dit, est-ce que tu serais choqué par un pointeur intelligent qui se
comporterait comme je le souhaite ?
Tu peux faire une classe qui se comporte comme tu le souhaites.
L'appeler "pointeur" me choquerait effectivement.
Cela dit, est-ce que tu serais choqué par un pointeur intelligent qui se
comporterait comme je le souhaite ?
Tu peux faire une classe qui se comporte comme tu le souhaites.
L'appeler "pointeur" me choquerait effectivement.
Tu peux faire une classe qui se comporte comme tu le souhaites.
L'appeler "pointeur" me choquerait effectivement.
Tu peux faire une classe qui se comporte comme tu le souhaites.
L'appeler "pointeur" me choquerait effectivement.
Tu peux faire une classe qui se comporte comme tu le souhaites.
L'appeler "pointeur" me choquerait effectivement.