[comp.lang.c++] conversions

vaughan@puma.cad.mcc.com (Paul Vaughan) (04/12/90)

The following program compiles cleanly under g++-1.37.1, but gets
three errors under cfront (Sun CC, actually).

---------------------------
class Int {
  int i;
public:
  Int(int j) : i(j) {}
  Int(Int& I) { i = I.i; }
  operator int() { return i; }
  operator int&() { return i; }
};

main() {
  Int i = 4;
  i += i;               // line 29
}

------------------------
CC -c convert.cc
CC  convert.cc:
"convert.cc", line 30: error: ambiguous conversion of Int
"convert.cc", line 30: error: ambiguous conversion of Int
"convert.cc", line 30: error: bad operand types Int  Int  for +=
3 errors

Any comments on why CC generates these errors, and whether or not this
is the right thing to do?  I realize that a class that works Exactly
like an int for both reading and assignment probably isn't very
useful, but should I be able to do it this way?

 Paul Vaughan, MCC CAD Program | ARPA: vaughan@mcc.com | Phone: [512] 338-3639
 Box 200195, Austin, TX 78720  | UUCP: ...!cs.utexas.edu!milano!cadillac!vaughan

spencer@egypt.mpr.ca ( Reid Spencer) (04/13/90)

In article <7633@cadillac.CAD.MCC.COM>, vaughan@puma.cad.mcc.com (Paul
Vaughan) writes:
> 
> The following program compiles cleanly under g++-1.37.1, but gets
> three errors under cfront (Sun CC, actually).
> 
example omitted.
> 
> Any comments on why CC generates these errors, and whether or not this
> is the right thing to do?  I realize that a class that works Exactly
> like an int for both reading and assignment probably isn't very
> useful, but should I be able to do it this way?
> 

I'm not sure what you were intending with this example, but at first
appearances it seems you
simply forgot to override the "+=" operator for class "Int". I think,
perhaps that you expected
cfront to use the constructor to add the value of i to itself. However,
even if that were semantically
possible it wouldn't provide the results you want (i.i being 8, not 4).
Why g++ accepts this program,
I don't know. It's probably a bug in g++. cfront seems to be giving you
the right messages.
Here's the program with some modifications I made:

------------------------------------------
extern "C" { int printf(char *, ...); };			// new

class Int {
  int i;
  public:
    Int(int j) : i(j) {}
    Int(Int& I) { i = I.i; }
    operator int() { return i; }
    operator int&() { return i; }
    Int & operator +=(Int &j) { i += j.i; return *this; }	// new
    Int & operator +=(int j) { i += j; return *this; }		// new
};

main() {
  Int i = 4;
  i += i;               // line 29
  i += 1;							// new
  printf("i.i is %d\n", int(i));				// new
}
----------------------------------------------

The printf statement should print "i.i is 9". This kind of problem is a
common misperception in C++.
Please make note of the following statement: "the semantics of
initialization and assignment are
different". See Lippman's book "C++ Primer", pp. 243 and 268 for
details. Also in Stroustrup, pp 178-180.

Hope this helps ...
_______________________________________________________________________________
Reid Spencer
Software Engineer		  Voice:    (604) 293-5334
MPR TelTech, Ltd.	  	  Fax:      (604) 293-5787
8999 Nelson Way, Burnaby, BC	  Internet: spencer@egypt.mpr.ca
Canada V5A 4B5			  UUCP:     uw-beaver!ubc-cs!eric!egypt!spencer

jimad@microsoft.UUCP (Jim ADCOCK) (04/14/90)

In article <7633@cadillac.CAD.MCC.COM| vaughan@puma.cad.mcc.com (Paul Vaughan) writes:
|
|The following program compiles cleanly under g++-1.37.1, but gets
|three errors under cfront (Sun CC, actually).
|
|---------------------------
|class Int {
|  int i;
|public:
|  Int(int j) : i(j) {}
|  Int(Int& I) { i = I.i; }
|  operator int() { return i; }
|  operator int&() { return i; }
|};
|
|main() {
|  Int i = 4;
|  i += i;               // line 29
|}
|
|------------------------
|CC -c convert.cc
|CC  convert.cc:
|"convert.cc", line 30: error: ambiguous conversion of Int
|"convert.cc", line 30: error: ambiguous conversion of Int
|"convert.cc", line 30: error: bad operand types Int  Int  for +=
|3 errors
|
|Any comments on why CC generates these errors, and whether or not this
|is the right thing to do?  I realize that a class that works Exactly
|like an int for both reading and assignment probably isn't very
|useful, but should I be able to do it this way?

See Hansen "The C++ Answer Book" pg 251, etc.

My question would be why g++ accepts this program?  To do so surely 
represents an extension to the language.  I would guess this might be
because g++ interprets x += y as x = x + y and counts on the optimizer
to keep x from being evaluated more than once?

---

Given that += is not overloaded in Int, the += referred to must be of
the form int x += int y.  

How then does the compiler make the int x out of
an Int i?  There are two ways:  Use operator int or use operator int&.
The disambiguating rules of C++ do not say which operator to use,
therefor the left hand side "x" is ambiguous.

How does the compiler make the int y out of
an Int i?  There are two ways:  Use operator int or use operator int&.
The disambiguating rules of C++ do not say which operator to use,
therefor the right hand side "y" is ambiguous.

So we cannot do the conversions.  Is there then a += we can use given 
an Int += Int ?  No.  

---

Please note that Hanson's comments about not being able to differentiate
pre and post inc and dec have been superceeded by popular demand --
to differentiate declare:

	operator++()		// prefix  ++a
	operator++(int);	// postfix a++

-- assuming you have a very recent release compiler that actually supports
this hack.

[ This according to the illuminated bible section 13.4.7 ]

jimad@microsoft.UUCP (Jim ADCOCK) (04/14/90)

>I realize that a class that works Exactly
>like an int for both reading and assignment probably isn't very
>useful, but should I be able to do it this way?

Actually, such a beast might actually be vaguely useful -- because it differs
from int in one important way:  INT is a first-class class and as 
such can be inherited from, whereas int is a primitive.

Consider a class LINK and a class INT:  create LINKED_INT by multiplying
inheriting from LINK and INT.  LINKED_INTs can be linked together and
tranversed using the capabilities of LINK, and LINKED_INTs can be used
as-if ints in math expressions.  ....one could then go on and use these
capabilities to make queues of INTs or stacks of INTs if one was really
perverse....  Weak example, but you get my drift.

c60c-2ca@e260-2d.berkeley.edu (Andrew Choi) (04/14/90)

In article <7633@cadillac.CAD.MCC.COM> vaughan@puma.cad.mcc.com (Paul Vaughan) writes:
>
>The following program compiles cleanly under g++-1.37.1, but gets
>three errors under cfront (Sun CC, actually).
>
>---------------------------
>class Int {
>  int i;
>public:
>  Int(int j) : i(j) {}
>  Int(Int& I) { i = I.i; }
>  operator int() { return i; }
>  operator int&() { return i; }
>};
>
>main() {
>  Int i = 4;
>  i += i;               // line 29
>}
>
>------------------------
>CC -c convert.cc
>CC  convert.cc:
>"convert.cc", line 30: error: ambiguous conversion of Int
>"convert.cc", line 30: error: ambiguous conversion of Int
>"convert.cc", line 30: error: bad operand types Int  Int  for +=
>3 errors

The code is incorrect because the user-defined conversion, namely,
"operator int()" is ambiguous.  Also, this conversion is not applied in
line 29, resulting in the third error message.

For the first error, please consider the following:

	Int i;
	i = i + 3;

For the second instance of i (the r-value), either "operator int()" or
"operator int&()" can be applied to convert "i" to an integer.


For the second error, the conversion "operator int()" is not applied
because there is no indication that it should be invoked since no integer
is involved in that expression.  Rather, the compiler is looking for
the function "operator +=(Int &, Int)".


Andrew Choi
Internet Address:  c60c-2ca@web.berkeley.edu
Standard Disclaimer