jj@idris.id.dk (Jesper Joergensen [ris]) (02/23/90)
ENVIRONMENT
===========
Compiler: G++ version 1.36.4 (configured for 'vax')
Back-end: GCC version 1.36.93 (configured for 'vax')
System: Ultrix version 2.2-1 Worksystem v1.1 System #2
Machine: DEC VAXstation 2000
SUMMARY Main problem
====================
Given a hierarchy of four different classes:
ID, Prod, Sum and Expr.
with the following implicit upward conversions (using constructors):
ID --> Prod
Prod --> Sum
Sum --> Expr
and a single backward conversion (using conversion operators):
Expr --> Sum & (NOTICE it is a reference to Sum)
then the call of an overloaded operator:
Sum operator*(const Sum &, const Prod &) ;
Sum operator*(const Sum &, const ID & ) ;
is flagged as ambiguous when given arguments of the classes Expr and ID
respectively.
The first argument of class Expr MUST be converted to class Sum, there is
no other possibility for a match and it is possible to do it. In any case
there will always be an exact match for the second argument of class ID, so
no implicit conversion is needed and there is therefore no ambiguity.
More comments follow after the example below.
SIDE ISSUE
==========
According to my documentation (Lippman), the language does not distinguish
between object and references to objects of the same class when type
matching is considered. In the below example I had to define a conversion
form `Expr' to `reference to Sum' in order to match the first argument
of the overloaded `operator*'. If I only had a conversion from `Expr' to
`Sum' then no match could be found at all !!
Please check this out as well ....
If you think that the conversion rules of the C++ language is just one hell
of a pain in standard output then I certainly can agree with you !! Just
thinking of trying to implement such a mess myself gives me the creeps, so
if you make bugs in doing this part of the compiler, then you are certainly
excused.
EXAMPLE PROGRAM WITH COMPILATION
================================
***** SESSION START *****
% cat implconvtest.cc
class ID { // Elementary class
public:
ID() { }
} ;
class Prod { // First level container class
ID member ;
public:
Prod() { }
Prod(const ID &id) { member = id ; } // can be initialised from elementary
} ;
class Sum { // Second level container class
Prod member ;
public:
Sum() { } // can be initialised from first level
Sum(const Prod &prod) { member = prod ; }
} ;
Sum operator*(const Sum &, const Prod &) ;
Sum operator*(const Sum &, const ID & ) ;
class Expr { // Third level container class
Sum member ;
public:
Expr() { } // can be initialised from second level
Expr(const Sum &sum) { member = sum ; }
operator Sum &() { return member ; } // and converted implicitly back
} ;
int main(int argc, const char *argv[]) {
ID id ;
Expr exp ;
Sum sum ;
sum = sum * id ; // OK: exact type match !!
sum = exp * id ; // Why is this call ambiguous ????
// exp MUST be converted to Sum and
// then id matches second arg. exactly
return 0 ;
}
% g++ -v implconvtest.cc -S
g++ version 1.36.4 (based on GCC 1.36.93)
/usr/local/lib/gcc-cpp -+ -v -undef -D__GNUC__ -D__GNUG__ -D__cplusplus -Dvax -Dunix -D__vax__ -D__unix__ implconvtest.cc /usr/tmp/cc006932.cpp
GNU CPP version 1.37
/usr/local/lib/gcc-cc1plus /usr/tmp/cc006932.cpp -quiet -dumpbase implconvtest.cc -version -o implconvtest.s
GNU C++ version 1.36.4 (based on GCC 1.36.93) (vax) compiled by GNU C version 1.36.93.
default target switches: -munix
implconvtest.cc: In function int main (int, const char **):
implconvtest.cc:36: type conversion required for type `ID'
implconvtest.cc:36: call of overloaded `op$mult' is ambiguous
%
****** SESSION END ******
I thought that the rule of disallowing ambiguous conversions only implied
when a conversion was actually required, here we have an exact match for
the second argument.
BTW I am not sure whether it actually is the second argument that is
causing the problem, i.e. I think that more specific error messages
refering to argument numbers and describing the possible ambiguous
conversions would be highly appropriate in cases like this. I had to go
back and do the work, which the compiler had already done (incorrectly).
The rest is up to you, good luck ....
Jesper Jorgensen jj@idris.id.dk
Research associate
Department of Computer Science
Technical University of Denmark
DK-2800 Lyngby
DENMARK