[comp.lang.c++] coercion of x op= y verses x = x op y ???

jima@hplsla.HP.COM (Jim Adcock) (10/05/89)

// g++ 1.35.x accepts the following, AT&T 2.0 rejects it.  Which is "right"?
// What are the general coercion/overloading rules for x =op y verses
// x = x op y?  [this seems to be another version of lvalue issues]

extern "C" {int printf(const char* const p, ...);};

class Int
{
  private: int i;
  public:  
    Int(int I=0):i(I){}
    operator int(){return i;}
};

void main()
{
  Int I=10;
  printf("%d\n",(int)I);
  I = I * I;			// okay by both g++ 1.35.x and AT&T 2.0
  printf("%d\n",(int)I);
  I *= I; 			// g++ 1.35.x accepts, 2.0 calls it an error
  printf("%d\n",(int)I);
}

shankar@hpclscu.HP.COM (Shankar Unni) (10/06/89)

>   I = I * I;			// okay by both g++ 1.35.x and AT&T 2.0
>   I *= I; 			// g++ 1.35.x accepts, 2.0 calls it an error

I think the key here is that in the first case, you are assigning to I a
value with an implicit constructor (Int(int)).

In the second case, you are either applying a "*=" operator to an Int (no
such operator defined), or to an int (which is generated by a function
call, which is not an lvalue).

I don't know what to say here - "gcc" seems to "Do What I Mean, Not What I
Say", which is nice and friendly, but I don't think this is legal..

Just one of those gotcha's (sigh!)
----
Shankar.

jima@hplsla.HP.COM (Jim Adcock) (10/10/89)

>In the second case, you are either applying a "*=" operator to an Int (no
>such operator defined), or to an int (which is generated by a function
>call, which is not an lvalue).

In which case, seems to me that coercion oerators should be considered to
return a reference, so as to be legal in lvalue situations.  Otherwise
you can't use coercion operators for true polymorphism.  Where is it defined
whether coercion operators return values or lvalues?  Is there anyway to
declare which you'd like?

dog@cbnewsl.ATT.COM (edward.n.schiebel) (10/11/89)

From article <6590286@hplsla.HP.COM>, by jima@hplsla.HP.COM (Jim Adcock):
>>In the second case, you are either applying a "*=" operator to an Int (no
>>such operator defined), or to an int (which is generated by a function
>>call, which is not an lvalue).
> 
> In which case, seems to me that coercion oerators should be considered to
> return a reference, so as to be legal in lvalue situations.  Otherwise
> you can't use coercion operators for true polymorphism.  Where is it defined
> whether coercion operators return values or lvalues?  Is there anyway to
> declare which you'd like?

You get to declare the coercion operators, so you decide.  In general,
the operators might not return a reference since the result may be 
computed.  Also, you may not want to allow the coercion operator to
return a reference to private data anyway as this violates data
hiding principles.

	Ed Schiebel
	AT&T Bell Laboratories
	dog@vilya.att.com

jima@hplsla.HP.COM (Jim Adcock) (10/12/89)

// okay, okay -- the following "works" -- I don't know *why* I couldn't figure
// out how to do this earlier.  Unfortunately, now you can't explictely 
// coerce to (int), as may be "required" to send Int to a "C" routine like
// printf.  Instead you have to coerce to (int&) -- So now users have to
// remember if a class defines an (int) coercion or and (int&) coercion.
// [Its not practical to have both, since that results in mega-ambiguities]

// -- And no, I'm not really writing an "Int" class.  "Int" is just a 
// metaphor for writing C++ classes supporting "as-if" polymorphism.  For
// example, one might want to write an "IntStack" where the top-of-stack can
// be used "as-if" it were an int.

extern "C" {int printf(const char* const p, ...);};

class Int
{
  private: int i;
  public:  
    Int(int I=0):i(I){}
    operator int&(){return i;}
};

void main()
{
  Int I=10;
  printf("%d\n",(int&)I);
  I = I * I;			// okay by both g++ 1.5.x and AT&T 2.0
  printf("%d\n",(int&)I);
  I *= I; 			// g++ 1.35.x accepts, 2.0 accepts it too
  printf("%d\n",(int&)I);
}