Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Ambiguity of code involving a template conversion operator

0 views
Skip to first unread message

Giovanni Bajo

unread,
May 1, 2003, 3:17:23 PM5/1/03
to
Hello,

look at this snippet:
----------------------------------------------------------------------------
-------
struct Foo
{
Foo() {}
Foo(int) {}
};

struct B
{
template <class T>
operator T() { return T(); }
};

struct D : B
{
operator Foo() { return Foo(); }
};

int main()
{
D d;
static_cast<Foo>(d);
return 0;
}
----------------------------------------------------------------------------
-------

Is this code ambigous or not? GCC and Comeau (strict mode) rejects it, but
other compilers don't.
My understanding is that it's ambigous because there are two ways to convert
B to Foo: one through the implicit copy constructor (and D::operator Foo()),
and one through the custom constructor (and B::operator T() specialized as
B::operator int()). There is no way to disambiguate between them, because
there is no way to disambiguate between Foo(int) and Foo(const Foo&), and
you cannot say that using one conversion operator is better than another.

But some compilers seem to think that using the non-template conversion
operator is better than using the template one (pretty much as choosing a
non-template function in an overload set is better than specialize and use a
template function). I also heard that D::operator Foo() should be preferred
because it does not require an implicit conversion to B* for this (but I
really can't find such a rule in the standard).

Comments?
--
Giovanni Bajo

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

Victor Bazarov

unread,
May 1, 2003, 4:22:30 PM5/1/03
to
"Giovanni Bajo" <no...@sorry.com> wrote...
> look at this snippet:
> --------------------------------------------------------------------------


So, let me try to get this straight. The static_cast<Foo>(d)
is basically the same as

Foo f(d); // where 'f' is an "invented" variable,
// the Standard uses that term

That means either

D -> B -> template<> B::operator int() -> int => Foo(int)
SC UDC EM
or

D -> D::operator Foo() -> const Foo& => Foo(const Foo&)
UDC RB

Both sequences are user-defined, about which the Standard says
that there is no way to determine which one is better unless
one is a sub-sequence of the other, IIRC (I am really not very
good at this).

The Standard also says that any template conversion functions
require the exact match after them (we have that), and that they
are considered in the same set along with other conversion
functions (13.3.1/7).

Victor
--
Please remove capital A's from my address when replying by mail

0 new messages