public inbox for gcc-prs@sourceware.org
help / color / mirror / Atom feed
From: "Giovanni Bajo" <giovannibajo@libero.it>
To: nobody@gcc.gnu.org
Cc: gcc-prs@gcc.gnu.org,
Subject: Re: c++/3708: [2003-01-02] static_cast between classes finds ambiguous base conversion
Date: Thu, 01 May 2003 01:56:00 -0000	[thread overview]
Message-ID: <20030501015602.11514.qmail@sources.redhat.com> (raw)

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 5658 bytes --]

The following reply was made to PR c++/3708; it has been noted by GNATS.

From: "Giovanni Bajo" <giovannibajo@libero.it>
To: "P Hornby" <p.hornby@ned.dem.csiro.au>
Cc: <gcc-gnats@gcc.gnu.org>,
	<gcc-bugs@gcc.gnu.org>,
	<nobody@gcc.gnu.org>,
	<gcc-prs@gcc.gnu.org>,
	<nathan@gcc.gnu.org>
Subject: Re: c++/3708: [2003-01-02] static_cast between classes finds ambiguous base conversion
Date: Thu, 1 May 2003 03:55:04 +0200

 P Hornby <p.hornby@ned.dem.csiro.au> wrote:
 
 > Long ago I eliminated the template, to get
 >
 > class B
 > {
 > public:
 >     B() {}
 >
 >     operator int () { return 1; }
 > };
 >
 > class D : public B
 > {
 > public:
 >     D () {}
 >
 >     operator Foo () { return Foo(1); };
 > };
 
 Which is still ambigous for both GCC and Comeau.
 
 > I seem to recall that D's methods are to be preferred over any of B's in
 > the event of such conflicts.
 
 That would be very strange, I never heard of a situation where methods of
 the most derived class are preferred over members of a less derived class to
 resolve ambiguity.
 
 > I also recall something that implied that
 > such conflict resolution had a limit on the complexity, and that this
 > limit was greater than a single direct call to a method of a class.
 
 I am not sure about what you mean here.
 
 > forget. In any case, the template version of the conflict is excluded on
 > the grounds that the D::operator Foo() -> Foo::Foo(const Foo&) requires
 > no template instantiation. (under the rule that the less instantiated
 > resolution yields to the more instantiated (in this case explict)
 > resolution).
 
 I think you're slightly missing the point. There is no ambiguity between
 operator Foo() and template <class  T> operator T(). Let's go step by step.
 
 The compiler needs to convert "d" (of type D) to type Foo. Since Foo() has a
 constructor taking a parameter of type "int", the compiler knows that the
 conversion can be done directly (finding an user-defined conversion to Foo,
 and calling the copy constructor) or indirectly (finding an user-defined
 conversions to int and calling the custom constructor). In the standard,
 there is nothing on why a constructor might be preferred over the other, so
 the conversion to type Foo() is not "better" in any way to the conversion to
 type int, since both have an accessible constructor in Foo (the implicit
 copy constructor for the former, the explicit custom constructor for the
 latter).
 
 So, the compiler just found out it can try to convert to either Foo or int.
 It checks for custom conversion functions, and it finds two of them: a
 conversion to Foo, and a template conversion operator. One is in B and one
 is in D, but §12.3p5 says "[...]A conversion function in a derived class
 does not hide a conversion function in a base class unless the two functions
 convert to the same type[...]". So both of them are visible.
 First, let's say that the compiler tries to convert to int. The non-template
 operator obviously cannot be used, but the template operator can be
 instanciated with type int. So the compiler now know that there is an
 available conversion from D to int, through the template operator in B.
 Second, it tries to see if it's possible to convert Foo to int. In this
 case, the compiler finds that there is a non-template operator Foo() which
 can be used, but also a template operator that could be instanciated with
 type Foo. So what? Again §12.3p5: "Function overload resolution selects the
 best conversion function to perform the conversion". Thus, the compiler
 prefers the non-template version over the template one (for the usual
 overaload rules).
 
 As you see, the compiler ends up with two valid paths to perform the
 required conversion. One path goes through conversion to int (thanks to the
 custom constructor) and one path through conversion to Foo (thanks to the
 implicit copy constructor).
 
 > This would be the case if the conflict were to arise from a
 > D::operator T(), so why break the rule for B::operator T()? (I know why
 > the compiler is doing this, and it is very hard to fix. I understand why
 > you are keen to close it).
 
 No, it's wrong. Even if you move the template operator into D, there is
 still an ambiguity.
 In fact (again) the ambiguty is not about choosing between the non-template
 conversion operator and the template one. Remember that a group of
 conversion functions do not form an overload set. You seem to think as your
 code is in the same situation of:
 
 template <typename T>
 void foo(T a);
 
 void foo(int a);
 
 where the second overload is obviously preferred to the first if the
 function is called with a varible of type int. But here, the situation is
 different. There is no overload set. The ambiguity is between which
 constructor must be called! Both of them are accessible, both of them are
 reachable through custom conversion functions (which are not overloaded!
 they are different functions!), so there is no way to solve this ambiguity.
 
 To solve this as you think, there should be an explicit paragraph in the
 standard stating that, in case of ambiguity during a conversion, a
 conversion made through a non-template operator should be preferred over a
 conversion made through a template operator. But there is no such a rule.
 
 > As I've stated elsewhere g++ (and now Comeau) are the only compilers I
 > have encountered that do not resolve this conflict. I only ask that you
 > consider this once more before closing it. (You may run into a language
 > lawyer next time).
 
 Sure, there is no hurry. In case nobody helps us here, I'll bring the issue
 to comp.std.c++ soon.
 
 Giovanni Bajo
 


             reply	other threads:[~2003-05-01  1:56 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-05-01  1:56 Giovanni Bajo [this message]
  -- strict thread matches above, loose matches on Subject: below --
2003-05-02 11:35 giovannibajo
2003-05-01  1:26 P Hornby
2003-04-30 21:16 Giovanni Bajo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20030501015602.11514.qmail@sources.redhat.com \
    --to=giovannibajo@libero.it \
    --cc=gcc-prs@gcc.gnu.org \
    --cc=nobody@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).