Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

operateur =() MS VC

21 réponses
Avatar
Sylvain SF
VC 14 est idiot ou c'est moi ??

dans une classe Integer, j'ai:

void operator= (long);
void operator= (const Integer&);
void operator= (const Bytes&);
void operator= (const char*);

où "Bytes" est une classe définissant un byte-array.

pour des déclarations telles:

Integer a; // membre d'une classe

const Integer* n = ....... // expression déduite
a = *n; // ERROR

ou encore

Integer m = ..... // expression calculée
a = m; // ERROR

sur les 2 affect. de 'a' le compilo sort une erreur "operateur ambigu"
ne savant pas choisir entre =(const Integer&) et =(const Bytes&).
(pourquoi pas les 2 autres ?...)

la classe Integer ne défini aucun operateur de cast implicite vers Bytes

j'ai du mal à saisir ce qui l'empêche de voir qu'un Integer const est
un Integer const ! y'a une logique ... ou un bug ?
(VC 12 compilait très bien ces expressions).

Sylvain.

10 réponses

1 2 3
Avatar
Fabien LE LEZ
On Sun, 11 May 2008 02:41:37 +0200, "Sylvain SF"
:

dans une classe Integer, j'ai:

void operator= (long);


Il y a là un truc bizarre : normalement, un X::operator= devrait
renvoyer un "X&" :

X& X::operator= (...)
{
...
return *this;
}

void operator= (const Integer&);
void operator= (const Bytes&);
void operator= (const char*);

où "Bytes" est une classe définissant un byte-array.

pour des déclarations telles:

Integer a; // membre d'une classe

const Integer* n = ....... // expression déduite
a = *n; // ERROR


Il faudrait donner un code minimaliste qui exhibe l'erreur. Ce
faisant, il y a d'ailleurs de bonnes chances que tu découvres le
problème toi-même.

Je suis prêt à parier qu'aucun compilateur n'a jamais indiqué d'erreur
dans le code suivant :


class Bytes {};

class Integer
{
public:
Integer& operator= (long);
Integer& operator= (const Integer&);
Integer& operator= (const Bytes&);
Integer& operator= (const char*);
};

int main()
{
Integer a;
const Integer* n= new Integer;
a = *n;
}

Avatar
Sylvain SF
Fabien LE LEZ wrote on 11/05/2008 02:57:

Il y a là un truc bizarre : normalement, un X::operator= devrait
renvoyer un "X&" :


"pourrait" -- ici je préfère qu'il ne retourne rien.

Il faudrait donner un code minimaliste qui exhibe l'erreur. Ce
faisant, il y a d'ailleurs de bonnes chances que tu découvres le
problème toi-même.


le code était celui-là: "a = *n;" ... sauf que n est un ASN1Integer
et non un Integer, or ASN1Integer définissait (où 'n' est un Integer
membre):

operator Bytes () const { return n.getBytes(); }
operator const Integer& () const { return n; }

le 1ier cast est inélégant et source des pbs.

on ne relit jamais assez (et l'output de VC 14 est merdique à lire).

Sylvain.

Avatar
Fabien LE LEZ
On Sun, 11 May 2008 03:17:17 +0200, "Sylvain SF" :

Il y a là un truc bizarre : normalement, un X::operator= devrait
renvoyer un "X&" :


"pourrait" -- ici je préfère qu'il ne retourne rien.


Auquel cas il y a, à côté, un commentaire indiquant pourquoi -- ça
évite au lecteur de passer trop de temps à buter contre cette
bizarrerie.

Il faudrait donner un code minimaliste qui exhibe l'erreur. Ce
faisant, il y a d'ailleurs de bonnes chances que tu découvres le
problème toi-même.


le code était celui-là: "a = *n;"


Je parlais d'un code compilable.
Si tu écris

a = *n;

dans un fichier .cpp, ça ne compilera pas.


Avatar
Sylvain SF
Fabien LE LEZ wrote on 11/05/2008 03:36:
On Sun, 11 May 2008 03:17:17 +0200, "Sylvain SF" :

Il y a là un truc bizarre : normalement, un X::operator= devrait
renvoyer un "X&" :
"pourrait" -- ici je préfère qu'il ne retourne rien.



Auquel cas il y a, à côté, un commentaire indiquant pourquoi -- ça
évite au lecteur de passer trop de temps à buter contre cette
bizarrerie.


ce n'était pas le point !...

si Integer& operator= (const Integer&) était défini, alors le lecteur
risquerait de buter sur des (a, b, c, d étant des Integer):

a = b = c + d;
a = (b = c) + d;

je ne veux pas de ces écritures, ni des "(a = b).foo();",
d'ou le choix.

Sylvain.



Avatar
Fabien LE LEZ
On Sun, 11 May 2008 03:47:07 +0200, "Sylvain SF" :

a = b = c + d;
a = (b = c) + d;

je ne veux pas de ces écritures


Si a et b sont des int, l'écriture "a=b=3" est parfaitement valide, et
même assez commune.
Ce qui signifie que :
- Tu n'empêcheras pas cette écriture, puisqu'on peut l'utiliser
avec d'autres types. Et de toute façon, quelqu'un qui veut écrire un
code illisible, y arrivera sans peine.
- Du code valide avec int, ne l'est plus avec Integer. La classe
"Integer" est donc d'un maniement fondamentalement différent de int,
et son nom risque d'induire l'utilisateur en erreur.

Avatar
espie
In article <48265018$0$928$,
Sylvain SF wrote:
si Integer& operator= (const Integer&) était défini, alors le lecteur
risquerait de buter sur des (a, b, c, d étant des Integer):

a = b = c + d;
a = (b = c) + d;

je ne veux pas de ces écritures, ni des "(a = b).foo();",
d'ou le choix.


Mais c'est une deviation par rapport aux usages courants, qui disent
tres clairement: "la surcharge d'operateur, c'est suffisamment complique
comme ca, alors par pitie, respectez toujours la signature des operateurs
par defaut".

Donc a partir du moment ou ton code est publie(*), il *faut* le
documenter.

* note qu'en demandant de l'aide ici, c'est exactement ce que tu fais.

Avatar
James Kanze
On 11 mai, 11:58, (Marc Espie) wrote:
In article <48265018$0$928$,
Sylvain SF wrote:


[...]
Donc a partir du moment ou ton code est publie(*), il *faut*
le documenter.

* note qu'en demandant de l'aide ici, c'est exactement ce que tu fais.


Je ne suis pas tout à fait d'accord. Il y a publication, et
publication, et quand je poste quelque chose dans le news, en
général, c'est pour éclaircir ou démander sur un point précis.
Du coup, je me permets beaucoup de simplifications que je ne me
permettrais jamais dans du code réel. Dans ce cas-ci, je ne suis
pas d'accord avec Sylvain ; à mon avis, dans le C++, l'opérateur
d'affectation est un lvalue, et si pour une raison quelconque,
il ne faut pas qu'il renvoie une référence à l'objet, c'est une
signe que l'utilisation de l'opérateur (plutôt qu'une fonction
membre) est un abus du surcharge. (Mais Sylvain n'est
certainement pas le seul à se donner à ce genre de surcharge. Je
connais une bibliothèque C++ avec des classes qui supportent
certaines opérations sur des pointeurs, genre * et ->, mais qui
ne supportent pas la comparaison avec NULL.) Seulement, le
problème n'est pas la publication ici.

Aussi, à mon avis, tout code est pour « publication », c-à-d
conçu pour être lu par les autres. Même si le cercle des
lecteurs est assez restreint (disons les programmeurs qui
participent dans la revue, plus un ou deux programmeurs de
maintenance dans la même boîte).

--
James Kanze (GABI Software) email:
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

Avatar
Sylvain SF
Marc Espie wrote on 11/05/2008 11:58:

Donc a partir du moment ou ton code est publie(*), il *faut* le
documenter.
* note qu'en demandant de l'aide ici, c'est exactement ce que tu fais.


tu me demanderais alors de raconter ma vie sur un point qui:
- n'est pas la source du problème,
- n'a rien à voir avec la question posée.

ce type de documentation ne me parait pas indispensable ici.

pour ces besoins, une classe comme un Integer ne me parait pas
en tout point comparable à un POD quelconque, qu'il fasse des
entorses aux usages courants n'est pas un grand problème.
de fait 95% des operations (publiques) sur une telle classe
sont justement des opérateurs surchargés ou introduits,
l'utilisateur devra donc lire leurs définitions, celle du comme par exemple celle du post-incrément qui est également
void pour éviter le cout d'une copie.

Sylvain.

Avatar
Fabien LE LEZ
On Sun, 11 May 2008 17:23:03 +0200, "Sylvain SF" :

tu me demanderais alors de raconter ma vie sur un point qui:
[...]


...est surtout *la* grosse bizarrerie du code que tu as posté ici. On
ne peut pas voir un tel code sans se poser des questions.

pour ces besoins, une classe comme un Integer ne me parait pas
en tout point comparable à un POD quelconque, qu'il fasse des
entorses aux usages courants n'est pas un grand problème.


Tant que tu es la seule victime de ces bizarreries, en effet, ce n'est
pas gênant pour les autres.

de fait 95% des operations (publiques) sur une telle classe
sont justement des opérateurs surchargés ou introduits,
l'utilisateur devra donc lire leurs définitions,


Et les avoir en tête en permanence.
Sans oublier l'impossibilité d'utiliser du code générique (templates),
puisque l'interface est fondamentalement différente de toutes les
autres interfaces.

comme par exemple celle du post-incrément qui est également
void pour éviter le cout d'une copie.


Uh ? Pour le coup, je comprends de moins en moins. Quand on utilise le
"post-incrément", c'est justement parce qu'on a besoin d'une copie de
la valeur précédente. Sinon on utilise le "pré-incrément".

Avatar
Sylvain SF
Fabien LE LEZ wrote on 11/05/2008 17:54:
On Sun, 11 May 2008 17:23:03 +0200, "Sylvain SF" :

tu me demanderais alors de raconter ma vie sur un point qui:
[...]


....est surtout *la* grosse bizarrerie du code que tu as posté ici. On
ne peut pas voir un tel code sans se poser des questions.


oui ?!? il fait trop chaud ? on s'ennuie avec tous ces viaducs oisifs ?

Tant que tu es la seule victime de ces bizarreries, en effet, ce n'est
pas gênant pour les autres.


hmm, je ne suis que victime d'avoir mal lu mon code à 4h du mat...

Sans oublier l'impossibilité d'utiliser du code générique (templates)


tu sais bien que j'en utilise aucun.
(et traiter génériquement void ou X& ne gènerait en rien la généricité).

Quand on utilise le "post-incrément", c'est justement parce qu'on
a besoin d'une copie de la valeur précédente.


ou pas - compte le nb de tes boucles "for (, , i++)" pour voir.

Sylvain.


1 2 3