[comp.lang.c++] Pointers to sibling classes in conditional expressions

robertk@lotatg.lotus.com (Robert Krajewski) (04/25/91)

I have a function that returns a pointer to a parent class -- it looks
at its arguments, and then makes a new object (with new) either of
child class A, or B, depending on the arguments to this function. The
decision is made in a conditional expression, and the result is
returned:

Parent * MakeIt(...)
{	
	...
	return ( <cond> ? new A(...) : new B(...) );
}

g++ warns that the two expressions are of different types, and so does
MPW C++.

However, it seems to me that I shouldn't get a warning. (MPW C++
actually considers this an error.) Return value conversion ought to be
following the same rules as conversion of class pointer types. This
code should not produce warnings:

F(Parent * thing);

F(new A(...));
F(new B(...));

... and I would argue that something analogous is happening in the
conditional expression example above.

Is there anything in the ARM to contradict what I'm saying ? If so, do
I have a reasonable complaint that should be addressed in the
standards effort ?

mittle@blinn.watson.ibm.com (Josh Mittleman) (04/26/91)

In article <ROBERTK.91Apr25110048@lotatg.lotus.com>,
robertk@lotatg.lotus.com (Robert Krajewski) writes:
> I have a function that returns a pointer to a parent class -- it looks
> at its arguments, and then makes a new object (with new) either of
> child class A, or B, depending on the arguments to this function. The
> decision is made in a conditional expression, and the result is
> returned:
> 
> Parent * MakeIt(...)
> {	
> 	...
> 	return ( <cond> ? new A(...) : new B(...) );
> }
> 
> g++ warns that the two expressions are of different types, and so does
> MPW C++.

My initial reaction was that this is a compiler error.  ARM, p.78, lays out
the rules for correctly formed conditional expressions:

"If both the second and the third expressions are of arithmetic type, the
usual arithmetic conversions are performed to bring them to a common type.
Otherwise, if both the second and the third expressions are either a
pointer or a constant expression that evaluates to 0, pointer conversions
are performed to bring them to a common type.  Otherwise, if both the
second and the third expressions are either references, reference
conversions are performed to bring them to a common type.  Otherwise if
both the second and the third expressions are void, the common type is
void.  Otherwise if both the second and the third expressions are the same
class T, the common type is T.  Otherwise the expression is illegal."

I tried the following code, and got the same kind of error from the ATT
v2.1 compiler.  I still think it looks right.  Anybody see something that I
missed? 



class Parent { };

class A : public Parent { public: A(int); };

class B : public Parent { public: B(int); };

Parent* F(int i)
{
  return (i ? new A(i) : new B(i));  //  error:  type mismatch: A *  ?: B *
}

rae@alias.com (Reid Ellis) (04/30/91)

Josh Mittleman <mittle@blinn.watson.ibm.com> writes:
>My initial reaction was that this is a compiler error.  ARM, p.78, lays out
>the rules for correctly formed conditional expressions:
>
>"If both the second and the third expressions are of arithmetic type, the
>usual arithmetic conversions are performed to bring them to a common type.
>Otherwise, if both the second and the third expressions are either a
>pointer or a constant expression that evaluates to 0, pointer conversions
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>are performed to bring them to a common type.  Otherwise, if both the
>second and the third expressions are either references, reference
                                                         +++++++++
>conversions are performed to bring them to a common type.  Otherwise if
 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>both the second and the third expressions are void, the common type is
>void.  Otherwise if both the second and the third expressions are the same
>class T, the common type is T.  Otherwise the expression is illegal."

I think the problem is in the "^^" marked phrase above.  On first
reading, it would seem to indicate "(a pointer that evaluates to 0) or
(a constant expression that evaluates to 0)".  But after some thought,
and especially after reading the section marked with "+" above, it
would seem that that phrase should be read as "(a pointer) or (a
constant expression that evaluates to 0)".

Is this the case?  Are ?: expressions broken in AT&T cfront
derivatives for this reason?  Is the ANSI draft more explicit on this?

		"... and what about.. Naomie?"
			-- Electric Company

						Reid
--
Reid Ellis     1 Trefan Street Apt. E, Toronto ON, M5A 3A9
rae@utcs.toronto.edu        ||               rae@alias.com
CDA0610@applelink.apple.com ||      +1 416 362 9181 [work]

mittle@blinn.watson.ibm.com (Josh Mittleman) (05/01/91)

>"If both the second and the third expressions are of arithmetic type, the
>usual arithmetic conversions are performed to bring them to a common type.
>Otherwise, if both the second and the third expressions are either a
>pointer or a constant expression that evaluates to 0, pointer conversions
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>are performed to bring them to a common type.  Otherwise, if both the
>second and the third expressions are either references, reference
                                                         +++++++++
>conversions are performed to bring them to a common type.  Otherwise if
 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>both the second and the third expressions are void, the common type is
>void.  Otherwise if both the second and the third expressions are the same
>class T, the common type is T.  Otherwise the expression is illegal."

In article <1991Apr29.173219.29532@alias.com>, rae@alias.com (Reid
Ellis) writes:

> I think the problem is in the "^^" marked phrase above.  On first
> reading, it would seem to indicate "(a pointer that evaluates to 0) or
> (a constant expression that evaluates to 0)".  But after some thought,
> and especially after reading the section marked with "+" above, it
> would seem that that phrase should be read as "(a pointer) or (a
> constant expression that evaluates to 0)".

Good point.  It has also been pointed out that the problem of converting
two pointers to a common type is non-trivial, and may be indeterminate if
the two classes have two common base classes.  This last case *must*
generate an error, and it is not obvious how to design a conversion scheme
that could distinguish this case from other, determinate cases.

===========================================================================
Josh Mittleman (mittle@watson.ibm.com or joshua@paul.rutgers.edu)
J2-C28 T.J. Watson Research Center, PO Box 704, Yorktown Heights, NY  10598

rfg@NCD.COM (Ron Guilmette) (05/12/91)

In article <1991Apr29.173219.29532@alias.com> rae@alias.com (Reid Ellis) writes:
>
>Is this the case?  Are ?: expressions broken in AT&T cfront
>derivatives for this reason?  Is the ANSI draft more explicit on this?

Wel,, since you mentioned the rule which says that any constant expression
which evaluates to zero can stand in for a NULL pointer, I'd have to say
"Yes, cfront is broken".

I don't think that it's just the interaction with ?: however that brings
this to light.  As I recall there are lots of contexts in which a null
pointer value should be acceptable but where an expression like "5+7-2-10"
will get you an error.

-- 

// Ron ("Loose Cannon") Guilmette
// Internet: rfg@ncd.com      uucp: ...uunet!lupine!rfg
// New motto:  If it ain't broke, try using a bigger hammer.