Topic: Ambiguous conversion to base?


Author: rogero@howzatt.demon.co.uk ("Roger Orr")
Date: Sun, 30 Jul 2006 05:02:10 GMT
Raw View
Should this fragment compile?

class Base
{
};

class Derived : public Base
{
public:
   Derived( Derived const & );
   Derived( Base const ); // Note: no '&'
};

class Final : public Derived
{
   Final( Final const & f )
   : Derived( f ) {}
};

MSVC 2003 and Comeau say 'Yes'
g++ 3.4.4 and 4.0.2 say 'No':

copyctor.cpp: In copy constructor `Final::Final(const Final&)':
copyctor.cpp:15: error: call of overloaded `Derived(const Final&)' is
ambiguous
copyctor.cpp:9: note: candidates are: Derived::Derived(Base)
copyctor.cpp:8: note:  Derived::Derived(const Derived&)

As far as I understand it conversion from Final const & -> Derived const &
should be a better conversion than any conversion to Base.
Or have I missed something?

[ Yes, I know the code fragment exbihits dubious programming practices but I
want to know if it is legal :-) ]

TIA,
Roger Orr
--
MVP in C++ at www.brainbench.com


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Greg Herlihy" <greghe@pacbell.net>
Date: Sun, 30 Jul 2006 19:08:32 CST
Raw View
"Roger Orr" wrote:
> Should this fragment compile?
>
> class Base
> {
> };
>
> class Derived : public Base
> {
> public:
>    Derived( Derived const & );
>    Derived( Base const ); // Note: no '&'
> };
>
> class Final : public Derived
> {
>    Final( Final const & f )
>    : Derived( f ) {}
> };
>
> MSVC 2003 and Comeau say 'Yes'
> g++ 3.4.4 and 4.0.2 say 'No':
>
> copyctor.cpp: In copy constructor `Final::Final(const Final&)':
> copyctor.cpp:15: error: call of overloaded `Derived(const Final&)' is
> ambiguous
> copyctor.cpp:9: note: candidates are: Derived::Derived(Base)
> copyctor.cpp:8: note:  Derived::Derived(const Derived&)
>
> As far as I understand it conversion from Final const & -> Derived const &
> should be a better conversion than any conversion to Base.
> Or have I missed something?

I would vote with gcc - the call Derived( f ) does indeed appear to be
ambiguous. The two eligible functions Derived(Base) and Derived(const
Derived&) both require a derived-to-base conversion for the argument.
Therefore both functions are awarded Conversion rank.

Now, the "distance" of a derived-to-base conversion can often serve a
tiebreaker when deciding between two derived-to-base conversions. The
compiler will favor more "immediate" conversions (such as the one-hop
Final to Derived conversion) over those farther apart in the class
hierarchy (such as the two-hop Final to Base conversion). But the
compiler can apply this tiebreaker only when the parameters requiring
the conversions are both references, both pointers or both values. In
this case, one parameter is a reference and the other is a value. Since
the parameters do not agree in form, the tiebreaker never gets to be
excercised. The call to Derived remains ambiguous. (Note that changing
the parameters to be both references, both values or both pointers
resolves the ambiguity).

Moreover, an error seems the most appropriate outcome in this
situation. After all, whether to call a function with a value parameter
or with a reference parameter is a more important decision (and one
which the compiler wisely refrains from making itself) than which
derived-to-base class conversion is preferable.

Greg

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]