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