C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Pourquoi l'operateur -> const des smart ptr renvoie un non c
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French)
View previous topic :: View next topic  
Author Message
Aurelien Regat-Barrel
Guest





PostPosted: Wed Apr 26, 2006 5:06 pm    Post subject: Pourquoi l'operateur -> const des smart ptr renvoie un non c Reply with quote



Bonjour,
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 ?

Merci.

--
Aurélien Regat-Barrel
Back to top
Fabien LE LEZ
Guest





PostPosted: Wed Apr 26, 2006 7:06 pm    Post subject: Re: Pourquoi l'operateur -> const des smart ptr renvoie un n Reply with quote



On Wed, 26 Apr 2006 18:09:05 +0200, Aurelien Regat-Barrel
<nospam.aregatba (AT) yahoo (DOT) fr>:

Quote:
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.
Back to top
kanze
Guest





PostPosted: Thu Apr 27, 2006 9:06 am    Post subject: Re: Pourquoi l'operateur -> const des smart ptr renvoie un n Reply with quote



Aurelien Regat-Barrel wrote:

Quote:
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;

Pourquoi ? La const-ité d'un pointeur n'est pas la même chose
que la const-ité du pointé. À l'encontre d'une collection,
l'objet pointé ne fait pas partie du pointeur -- c'est un objet
complétement indépendant.

Pense au pointeurs bruts. Tu as bien :

int * pointeur_non_const_a_int_non_const ;
int * const pointeur_const_a_int_non_const ;
int const* pointeur_non_const_a_int_const ;
int const* const pointeur_const_a_int_const ;

Avec auto_ptr, ça donne :

auto_ptr< int > pointeur_non_const_a_int_non_const ;
auto_ptr< int > const pointeur_const_a_int_non_const ;
auto_ptr< int const > pointeur_non_const_a_int_const ;
auto_ptr< int const > const pointeur_const_a_int_const ;

Ou considère comment ça marche avec des typedef :

typedef int* Ptr ;
typedef int const* PtrConst ;
Ptr pointeur_non_const_a_int_non_const ;
Ptr const pointeur_const_a_int_non_const ;
PtrConst pointeur_non_const_a_int_const ;
PtrConst const pointeur_const_a_int_const ;

On peut alors remplacer les typedef avec :
typedef auto_ptr< int > Ptr ;
typedef auto_ptr< int const > PtrConst ;
sans problème, mais il faut toujours deux typedef, que ce soit
des pointeurs bruts ou des pointeurs intelligents.

(En passant, un peu de reflection sur les exemples ci-dessus
montrera clairement pourquoi il est préférable de toujours
mettre le const derrière, comme je fais.)

Note bien que dans le cas d'une collection, genre std::vector,
les éléments appartiennent à la collection, et font partie de
son état. On ne peut donc pas modifier un élément d'une
collection const. En revanche, les itérateurs fonctionnent comme
les pointeurs, ci-dessus : tu as un « iterator » et un
« const_iterator », et le const sur l'objet itérateur s'applique
à l'itérateur même, et non à l'élément auquel il réfère, c-à-d
:

vector< int >::iterator
iterateur_non_const_a_int_non_const ;
vector< int >::iterator const iterateur_const_a_int_non_const
;
vector< int >::const_iterator iterateur_non_const_a_int_const
;
vector< int >::const_iterator const iterateur_const_a_int_const ;

Quote:
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...

Mais tu ne veux pas d'erreur de compilation ici.

Quote:
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.

Quote:
:/
(cela dit ça marche avec boost, dans une certaine mesure).

Pas de problème avec shared_ptr, y compris avec les appels de
fonctions.

Quote:
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.

--
James Kanze GABI Software
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
Back to top
Aurelien Regat-Barrel
Guest





PostPosted: Thu Apr 27, 2006 10:06 am    Post subject: Re: Pourquoi l'operateur -> const des smart ptr renvoie un n Reply with quote

Fabien LE LEZ a écrit :
Quote:
On Wed, 26 Apr 2006 18:09:05 +0200, Aurelien Regat-Barrel
nospam.aregatba (AT) yahoo (DOT) 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 ?

--
Aurélien Regat-Barrel
Back to top
Aurelien Regat-Barrel
Guest





PostPosted: Thu Apr 27, 2006 10:06 am    Post subject: Re: Pourquoi l'operateur -> const des smart ptr renvoie un n Reply with quote

kanze a écrit :

Quote:
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é.

Quote:
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 :-/

Quote:
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

Le contraire m'aurait mis dans l'embarras :-)

--
Aurélien Regat-Barrel
Back to top
kanze
Guest





PostPosted: Thu Apr 27, 2006 4:06 pm    Post subject: Re: Pourquoi l'operateur -> const des smart ptr renvoie un n Reply with quote

Aurelien Regat-Barrel wrote:
Quote:
Fabien LE LEZ a écrit :
On Wed, 26 Apr 2006 18:09:05 +0200, Aurelien Regat-Barrel
nospam.aregatba (AT) yahoo (DOT) 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;

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.

Quote:
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.

--
James Kanze GABI Software
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
Back to top
kanze
Guest





PostPosted: Thu Apr 27, 2006 4:07 pm    Post subject: Re: Pourquoi l'operateur -> const des smart ptr renvoie un n Reply with quote

Aurelien Regat-Barrel wrote:
Quote:
kanze a écrit :

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

Et est-ce que ça marcherait avec :
typedef A* APtr ;
typedef A const* AConstPtr ;
?

Il y a des limites de ce qu'on peut faire avec des conversions
de type implicites. Est-ce que tu veux qu'on puisse convertir
tous les vecteurs, du moment que le type contenu dans un se
laisse convertir en type contenu dans l'autre. Que je puisse
affeecter un vector<double> à un vector<char>, c-à-d :

typedef std::vector< char > CVect ;
typedef std::vector< double > DVect ;

void Test( CVect ) ;

DVect dv ;
Test( dv ) ;

Note aussi que c'est assez rare de passer des vecteurs par
valeur. Mais si on passe par référence (const), attention au
dégat :

typedef std::vector< char > CVect ;
void Test( CVect const& ) ;

DVect dv ;
Test( dv ) ;

Du coup, j'ai une copie profonde que je n'ai peut-être pas
voulue. Ça coûte cher, copier tout un vecteur.

Note bien que si tu veux la copie, tu peux toujours écrire :

Test2( AConstVect( v.begin(), v.end() ) ) ;

C'est la façon à appliquer la conversion explicite sur chaque
élément du vecteur.

Quote:
du coup, j'hésite à utiliser const dans mes pointeurs
intelligents, et donc il perd son utilité au sein même de mes
classes :-/

Je ne sais pas. Dans l'ensemble, je crois que boost::shared_ptr
se comporte assez comme un pointeur brut à cet égard. Et j'avoue
que ces restrictions ne m'ont jamais causé de problèmes. Les
copies pûres et simples des vecteurs sont plutôt rares dans mon
code ; ce qui arrive souvent, en revanche, ce sont des
sous-ensembles -- une copie qui ne copie que certains éléments.
Et dans ce cas-là, la solution la plus simple, c'est un
itérateur filtrant de Boost, et le constructeur à deux
itérateurs du vecteur. Mais alors, si le sous-ensemble doit être
un vector< AConstPtr >, plutôt qu'un vector< APtr >, pas de
problème -- parce que je me sers du constructeur à deux
itérateurs, et que donc le compilateur cherche à faire la
conversion élément par élément, plutôt que sur le vecteur
complet.

--
James Kanze GABI Software
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
Back to top
Fabien LE LEZ
Guest





PostPosted: Thu Apr 27, 2006 8:07 pm    Post subject: Re: Pourquoi l'operateur -> const des smart ptr renvoie un n Reply with quote

On Thu, 27 Apr 2006 11:06:30 +0200, Aurelien Regat-Barrel
<nospam.aregatba (AT) yahoo (DOT) fr>:

Quote:
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.
Back to top
Aurelien Regat-Barrel
Guest





PostPosted: Fri Apr 28, 2006 1:06 pm    Post subject: Re: Pourquoi l'operateur -> const des smart ptr renvoie un n Reply with quote

kanze a écrit :

Quote:
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.

Je le sais, mais c'est une question d'habitudes : const char *,
const_iterator, ...

Quote:
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.

De toutes façons ça résoud pas le problème de mon vector<const>.

--
Aurélien Regat-Barrel
Back to top
Aurelien Regat-Barrel
Guest





PostPosted: Fri Apr 28, 2006 1:06 pm    Post subject: Re: Pourquoi l'operateur -> const des smart ptr renvoie un n Reply with quote

Fabien LE LEZ a écrit :

Quote:
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.

Je vais continuer avec shared_ptr alors.

--
Aurélien Regat-Barrel
Back to top
Fabien LE LEZ
Guest





PostPosted: Fri Apr 28, 2006 1:06 pm    Post subject: Re: Pourquoi l'operateur -> const des smart ptr renvoie un n Reply with quote

On Thu, 27 Apr 2006 22:03:36 +0200, Fabien LE LEZ
<gramster (AT) gramster (DOT) com>:

Quote:
Tu peux faire une classe qui se comporte comme tu le souhaites.
L'appeler "pointeur" me choquerait effectivement.

En fait, je m'aperçois que je fais assez souvent des classes
(non templates) de ce style, et que je les appelle généralement
"handle", "gestionnaire", ou quelque chose d'approchant.
Mais ces classes n'ont pas d'opérateur -> ou * : elles ont grosso modo
les mêmes fonctions que la classe "de base".

Par exemple :

class Machin
{
public:
void truc();
Machin (int n);
};

class HandleMachin
{
public:
HandleMachin() : ptr (0) {}
void CreerMachin (int n)
{ Machin* m= new Machin (n); std::swap(m,ptr); delete m; }
bool EstOk() const { return ptr != 0; }
void truc() { assert(EstOk()); ptr->truc(); }
~HandleMachin() { delete ptr; }
private:
Machin *ptr;
};

C'est un peu l'idiome "pimpl", sauf que le point de vue n'est pas le
même : pimpl sert à cacher les rouages internes d'une classe ; cette
technique-ci sert plutôt à faciliter l'usage d'une classe déjà faite.
Un peu comme un pointeur intelligent, en somme.
Back to top
Falk Tannhäuser
Guest





PostPosted: Fri Apr 28, 2006 2:06 pm    Post subject: Re: Pourquoi l'operateur -> const des smart ptr renvoie un n Reply with quote

Aurelien Regat-Barrel wrote:
Quote:
Après réflexion, je réalise que c'est au niveau des références qu'est le
problème. Ceci compile:

char a;
char const & b = a;

mais pas ceci:

char * a = 0;
char const * & b = a;

En fait, je ne comprends pas pourquoi.

char const c[] = "Parce que cela permettrait de casser la 'const correctness' !";
b = c;
std::strcpy(a, "Et voilà :-p !");

Falk
Back to top
Aurelien Regat-Barrel
Guest





PostPosted: Fri Apr 28, 2006 2:06 pm    Post subject: Re: Pourquoi l'operateur -> const des smart ptr renvoie un n Reply with quote

kanze a écrit :

Quote:
Il y a des limites de ce qu'on peut faire avec des conversions
de type implicites. Est-ce que tu veux qu'on puisse convertir
tous les vecteurs, du moment que le type contenu dans un se
laisse convertir en type contenu dans l'autre. Que je puisse
affeecter un vector<double> à un vector<char>, c-à-d :

typedef std::vector< char > CVect ;
typedef std::vector< double > DVect ;

void Test( CVect ) ;

DVect dv ;
Test( dv ) ;

Note aussi que c'est assez rare de passer des vecteurs par
valeur. Mais si on passe par référence (const), attention au
dégat :

typedef std::vector< char > CVect ;
void Test( CVect const& ) ;

DVect dv ;
Test( dv ) ;

Après réflexion, je réalise que c'est au niveau des références qu'est le
problème. Ceci compile:

char a;
char const & b = a;

mais pas ceci:

char * a = 0;
char const * & b = a;

En fait, je ne comprends pas pourquoi.

A peu de chose près, j'imagine que c'est la même règle qui s'applique
pour le refus d'initialiser une référence sur un template<T const> à
partir d'un template<T>.

Quote:
Du coup, j'ai une copie profonde que je n'ai peut-être pas
voulue. Ça coûte cher, copier tout un vecteur.

Note bien que si tu veux la copie, tu peux toujours écrire :

Test2( AConstVect( v.begin(), v.end() ) ) ;

C'est la façon à appliquer la conversion explicite sur chaque
élément du vecteur.

Je pense que je vais opter pour cette solution, avec un peu de chance le
compilateur fera une bonne optimisation.

Quote:
du coup, j'hésite à utiliser const dans mes pointeurs
intelligents, et donc il perd son utilité au sein même de mes
classes :-/


Je ne sais pas. Dans l'ensemble, je crois que boost::shared_ptr
se comporte assez comme un pointeur brut à cet égard. Et j'avoue
que ces restrictions ne m'ont jamais causé de problèmes. Les
copies pûres et simples des vecteurs sont plutôt rares dans mon
code ; ce qui arrive souvent, en revanche, ce sont des
sous-ensembles -- une copie qui ne copie que certains éléments.
Et dans ce cas-là, la solution la plus simple, c'est un
itérateur filtrant de Boost, et le constructeur à deux
itérateurs du vecteur. Mais alors, si le sous-ensemble doit être
un vector< AConstPtr >, plutôt qu'un vector< APtr >, pas de
problème -- parce que je me sers du constructeur à deux
itérateurs, et que donc le compilateur cherche à faire la
conversion élément par élément, plutôt que sur le vecteur
complet.

--
Aurélien Regat-Barrel
Back to top
Aurelien Regat-Barrel
Guest





PostPosted: Fri Apr 28, 2006 3:06 pm    Post subject: Re: Pourquoi l'operateur -> const des smart ptr renvoie un n Reply with quote

Falk Tannhäuser a écrit :

Quote:
En fait, je ne comprends pas pourquoi.


char const c[] = "Parce que cela permettrait de casser la 'const
correctness' !";
b = c;
std::strcpy(a, "Et voilà :-p !");

Ok. Avec un autre const, ça marche:

char * a = 0;
char const * const & b = a;

Du coup, je m'attends à pouvoir écrire:

std::vector<char> a;
std::vector<char> const & b = a; // OK
std::vector<char const> const & c = a; // :-(

mais je commence à trop nager pour pouvoir évaluer tout ce que cela
implique.

--
Aurélien Regat-Barrel
Back to top
Falk Tannhäuser
Guest





PostPosted: Fri Apr 28, 2006 10:06 pm    Post subject: Re: Pourquoi l'operateur -> const des smart ptr renvoie un n Reply with quote

Aurelien Regat-Barrel wrote:

Quote:
Ok. Avec un autre const, ça marche:

char * a = 0;
char const * const & b = a;

Du coup, je m'attends à pouvoir écrire:

std::vector<char> a;
std::vector<char> const & b = a; // OK
std::vector<char const> const & c = a; // Sad

std::vector<char const> ne passe pas parce que
le type qu'on met dans un vector doit supporter
l'affectation.

En revanche, on peut imaginer des conversions qui seraient parfaitement
sûres mais qui ne sont néanmoins pas supportées par le langage (sans doute
personne ne les a pas proposées pour la standardisation parce que
les cas où elles seraient utiles se présentent trop rarement dans
la pratique). Par exemple
std::vector<char*>::iterator ==> std::vector<char const*>::const_iterator
std::vector<char>::iterator* ==> std::vector<char>::const_iterator const*
(Note: Ces deux conversions passeront la compilation sur les implémentations
où 'std::vector<T>::[[const_]]iterator' est défini comme 'T [[const]]*'. Ces
implémentations semblent toutefois devenir de plus en plus rares ces jours-ci.)

Similairement, il pourrait aussi y avoir des conversions entre pointeurs
sur les fonctions comme
char* (*)() ===> char const* (*)()
void (*)(char const*) ===> void (*)(char*)

Falk
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.