Topic: overload resolution
Author: "Jim Fischer" <jfischer110@attbi.com>
Date: Sat, 22 Jun 2002 00:35:11 GMT Raw View
"Daqing-UA" <daqing@cs.ualberta.ca> wrote in message
news:aetla7$8k6$1@pulp.srv.ualberta.ca...
> void f(int, int);
> void f(char, char);
>
> char c;
> short s;
>
> f(c,s);
>
> g++ resolves the above f(c,s) to f(int, int); but according to my
> understanding of the resolution rules, it should have caused an ambiguity.
>
> For f(int, int), the conversions, char to int and short to int, are both
> promotions.
> For f(char, char), the first argument c is an exact match while the second
> is a standard conversion. Exact match is better than promotion but
promotion
> is better than standard conversion, so no one should win out and an
> ambiguity should have resulted.
>
> Any different explanation?
I beleve GNU g++ is correct in this case.
See section 13.3.3 "Best Viable Function" in the C++ standard. Specifically,
see Table 9 "conversions" in section 13.3.3.1.1, and paragraph 13.3.3.2/4.
<quote>
13.3.3.2/4 Standard conversion sequences are ordered by their ranks: an
Exact Match is a better conversion than a Promotion, which is a better
conversion than a Conversion. [etc...]
</quote>
So given the choice between integral promotion and integral conversion, the
compiler chooses integral promotion IAW 13.3.3.2/4.
Jim
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: "Daqing-UA" <daqing@cs.ualberta.ca>
Date: Thu, 20 Jun 2002 23:11:03 GMT Raw View
void f(int, int);
void f(char, char);
char c;
short s;
f(c,s);
g++ resolves the above f(c,s) to f(int, int); but according to my
understanding of the resolution rules, it should have caused an ambiguity.
For f(int, int), the conversions, char to int and short to int, are both
promotions.
For f(char, char), the first argument c is an exact match while the second
is a standard conversion. Exact match is better than promotion but promotion
is better than standard conversion, so no one should win out and an
ambiguity should have resulted.
Any different explanation?
--Daqing
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: inpact3 <inpact3@clr34el.der.edf.fr>
Date: 1997/12/03 Raw View
Yet another problem with overload resolution !
Look at the following code :
class A
{
public:
A (A& other) {}
operator int () { return 0; }
};
extern void foo (A); //-- foo-1
extern void foo (int); //-- foo-2
main()
{
foo (A());
}
If my reading of the CD2 is correct, foo-1 shall be selected as
the best viable function for the call :
- according to [over.best.ics] alinea 6 ("When the parameter has
a class type and the argument expression is an rvalue of the same
type, the implicit conversion sequence is an identity conversion."),
the ICS for foo-1 is identity.
- the ICS for foo-2 is an user-defined conversion.
The problem is that the initialization of the foo-1 parameter is
actually ill-formed (it binds a non-const reference to a temporary)
=> the selected overloading can not be used while another (legal)
overloading could be used !!
Did I miss something ? If not, is it what the committee intended ?
[ I know that the same problem can arise with access control
specifiers, but it is explicitly stated in the CD2 ; that's
not the case here AFAIK ]
Jerome CHAROUSSET
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Fergus Henderson <fjh@cs.mu.oz.au>
Date: 1997/12/03 Raw View
inpact3 <inpact3@clr34el.der.edf.fr> writes:
>Yet another problem with overload resolution !
I don't see any problem ;-)
>Look at the following code :
>
> class A
> {
> public:
> A (A& other) {}
> operator int () { return 0; }
> };
>
> extern void foo (A); //-- foo-1
> extern void foo (int); //-- foo-2
>
> main()
> {
> foo (A());
> }
>
>If my reading of the CD2 is correct, foo-1 shall be selected as
>the best viable function for the call :
>- according to [over.best.ics] alinea 6 ("When the parameter has
>a class type and the argument expression is an rvalue of the same
>type, the implicit conversion sequence is an identity conversion."),
>the ICS for foo-1 is identity.
>- the ICS for foo-2 is an user-defined conversion.
>
>The problem is that the initialization of the foo-1 parameter is
>actually ill-formed (it binds a non-const reference to a temporary)
>=> the selected overloading can not be used while another (legal)
>overloading could be used !!
>
>Did I miss something ?
I think not.
>If not, is it what the committee intended ?
Yes, I'm pretty sure it is.
>[ I know that the same problem can arise with access control
>specifiers, but it is explicitly stated in the CD2 ; that's
>not the case here AFAIK ]
Note that there are other instances where the same situation
(the best match being ill-formed, even though a different match
might be well-formed) can occur. Initializing a reference with
a bit-field is another example which the draft explicitly mentions
(see 13.3.3.1.4 [over.ics.ref] paragraph 4), but I wouldn't be
too surprised if there are others.
I don't consider any of these to be problems. The user can always
write the conversions explicitly if necessary. Better to say what you
mean than to have the compiler try to guess, because if the compiler
has to guess, then sometimes it will guess wrong.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: bill@gibbons.org (Bill Gibbons)
Date: 1997/12/03 Raw View
In article <34853A6D.371C@clr34el.der.edf.fr>,Jerome CHAROUSSET
<inpact3@clr34el.der.edf.fr> wrote:
> Yet another problem with overload resolution !
>
> Look at the following code :
>
> class A
> {
> public:
> A (A& other) {}
> operator int () { return 0; }
> };
>
> extern void foo (A); //-- foo-1
> extern void foo (int); //-- foo-2
>
> main()
> {
> foo (A());
> }
>
> If my reading of the CD2 is correct, foo-1 shall be selected as
> the best viable function for the call :
> - according to [over.best.ics] alinea 6 ("When the parameter has
> a class type and the argument expression is an rvalue of the same
> type, the implicit conversion sequence is an identity conversion."),
> the ICS for foo-1 is identity.
> - the ICS for foo-2 is an user-defined conversion.
>
> The problem is that the initialization of the foo-1 parameter is
> actually ill-formed (it binds a non-const reference to a temporary)
> => the selected overloading can not be used while another (legal)
> overloading could be used !!
>
> Did I miss something ? If not, is it what the committee intended ?
> [ I know that the same problem can arise with access control
> specifiers, but it is explicitly stated in the CD2 ; that's
> not the case here AFAIK ]
Author: Valentin Bonnard <bonnardv@pratique.fr>
Date: 1997/12/04 Raw View
inpact3 wrote:
> Yet another problem with overload resolution !
I don't see how it is a problem.
> Look at the following code :
>
> class A
> {
> public:
> A (A& other) {}
> operator int () { return 0; }
> };
>
> extern void foo (A); //-- foo-1
> extern void foo (int); //-- foo-2
>
> main()
> {
> foo (A());
> }
Not only foo-2 is selected as Bill Gibbons explainned,
but it's the way the new auto_ptr works (well, at least
it's close).
auto_ptr has a non const copy ctor, a converting ctor
and a convertion operator. The non const copy ctor isn't
considered for many sorts of copies. But Bill can
explain that magic better than me.
--
Valentin Bonnard mailto:bonnardv@pratique.fr
info about C++/a propos du C++: http://www.pratique.fr/~bonnardv/
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: inpact3 <inpact3@clr34el.der.edf.fr>
Date: 1997/12/04 Raw View
Fergus Henderson wrote:
> I don't see any problem ;-)
Actually, it's a problem FOR ME, because I feel uncomfortable with
corresponding parts of the CD2 and I had trouble finding what the
correct behaviour shall be.
Moreover, it appears that this is also a problem for others : even
the most valuable gurus do not agree ! See below...
Fergus Henderson wrote: [implying that foo-1 shall be selected ]
> >Did I miss something ?
> I think not.
> >If not, is it what the committee intended ?
> Yes, I'm pretty sure it is.
On the other side, Bill Gibbons wrote :
> So "foo-1" is not viable, and "foo-2" is chosen.
Last but not least, Valentin Bonnard approved this argument.
For me, I keep saying that foo-1 shall be selected because the end
of 13.3.2 paragraph 3 does no apply : the sentence begins with "If
the parameter has reference type..." which is not the case. Moreover,
[over.best.ics] alinea 6, a more "specialized" paragraph , clearly
states that the ICS for foo1-1 EXISTS and IS IDENTITY.
I think this discussion prove at least that the CD2 is not explicit
enough on this subject...
Any comments ?
Jerome CHAROUSSET
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/12/04 Raw View
bill@gibbons.org (Bill Gibbons) writes:
>Jerome CHAROUSSET <inpact3@clr34el.der.edf.fr> wrote:
>
>> Yet another problem with overload resolution !
>>
>> Look at the following code :
>>
>> class A
>> {
>> public:
>> A (A& other) {}
>> operator int () { return 0; }
>> };
>>
>> extern void foo (A); //-- foo-1
>> extern void foo (int); //-- foo-2
>>
>> main()
>> {
>> foo (A());
>> }
>>
>> If my reading of the CD2 is correct, foo-1 shall be selected as
>> the best viable function for the call :
>> - according to [over.best.ics] alinea 6 ("When the parameter has
>> a class type and the argument expression is an rvalue of the same
>> type, the implicit conversion sequence is an identity conversion."),
>> the ICS for foo-1 is identity.
>> - the ICS for foo-2 is an user-defined conversion.
>>
>> The problem is that the initialization of the foo-1 parameter is
>> actually ill-formed (it binds a non-const reference to a temporary)
>> => the selected overloading can not be used while another (legal)
>> overloading could be used !!
>>
>> Did I miss something ? If not, is it what the committee intended ?
>> [ I know that the same problem can arise with access control
>> specifiers, but it is explicitly stated in the CD2 ; that's
>> not the case here AFAIK ]
>
>From CD2, 13.3.2 paragraph 3 (this did not change in the FDIS):
>
> Second, for F to be a viable function, there shall exist for each
> argument an implicit conversion sequence (13.3.3.1) that converts that
> argument to the corresponding parameter of F. If the parameter has
> reference type, the implicit conversion sequence includes the operation
> of binding the reference, and the fact that a reference to non-const
> cannot be bound to an rvalue can affect the viability of the function.
>
>So "foo-1" is not viable, and "foo-2" is chosen.
This doesn't follow. The second sentence in the above-quoted paragraph
does not apply here, because the parameter in question does not have
reference type. The type of foo-1's parameter is `A', not `A&'.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "V.A.Neelesh" <v_a_neelesh@hotmail.com>
Date: 1997/12/06 Raw View
Hi,
Both u and Bill are right.
According to 13.3.3.1 6th para foo1 is viable function and
according to 13.3.2 3rd para foo2 is also viable function
but according to 13.3.3(over.match.best) 1st para - Since foo1 requires
no conversion than foo2 which requires conversion, foo1 should be the
best viable function
Neelesh
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: bill@gibbons.org (Bill Gibbons)
Date: 1997/12/06 Raw View
In article <665pme$7ok@mulga.cs.mu.OZ.AU>, fjh@mundook.cs.mu.OZ.AU (Fergus
Henderson) wrote:
> >From CD2, 13.3.2 paragraph 3 (this did not change in the FDIS):
> >
> > Second, for F to be a viable function, there shall exist for each
> > argument an implicit conversion sequence (13.3.3.1) that converts that
> > argument to the corresponding parameter of F. If the parameter has
> > reference type, the implicit conversion sequence includes the operation
> > of binding the reference, and the fact that a reference to non-const
> > cannot be bound to an rvalue can affect the viability of the function.
> >
> >So "foo-1" is not viable, and "foo-2" is chosen.
>
> This doesn't follow. The second sentence in the above-quoted paragraph
> does not apply here, because the parameter in question does not have
> reference type. The type of foo-1's parameter is `A', not `A&'.
OK, under a strict reading of this paragraph, I have to agree.
The intent appears to be that it must be possible to initialize the
parameter (ignoring conversion ambiguity problems and access problems),
but the actual wording does not say that.
(Even so, I'd like to hear Steve A.'s interpretation on this one.)
-- Bill Gibbons
bill@gibbons.org
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: chopps@water.emich.edu (Christian E. Hopps)
Date: 1995/09/18 Raw View
Before my main question: I use the term ill-formed below because
that is what the WP used. Is an ambiguous call ill-formed? I am
not familiar with this term and so I want to make sure the compiler
is required to issue some error...
When figuring out which operator to use is any precedence given to
operators defined in the class? Basically my interpretation of the
WP of the following situation is that the "function call" is ill-formed.
class A {
...
A(int);
operator int();
bool operator =3D=3D(A& a);
...
};
void func()
{
A a;
bool result =3D
(a =3D=3D 4); // ill-formed?
The candidate functions are:
bool A::operator=3D=3D(A& a); // 1
bool built-in::operator(int, int); // 2
(1) requires a user-defined conversion (A::A(4)) on its second
argument. (2) requires a user-defined conversion (a.A::operator int())
on its first argument.
Someone in another newsgroup was inquiring as to whether their
compiler's selection of the member operator was a bug. My first
guess was that it was not. I think I based the guess on the fact
that the built-in operators would exist in the global scope and that
therefore the definition of the member operator would hide the global
built-in version. It seems now that this was a bad assumption and
that, unless the explicit function syntax is used, no hiding of
operators takes place.
Do I have things straight now? (Zooming around the WP with regards to
overload resolution tends to make me feel less confident in what I
think I found.)
Overload resolution can probably not be made any simpler and that is
too bad because right now its pretty complex. The scoping rules for
normal functions do make things less complex though. That is, while
designing, section 13 in it full "glory", is probably too much to
effect my decisions. Instead I'll probably use the normal scoping
rules. It also helps that I avoid Class([integral-type]) and
Class::operator [integral-type]() like the plague. :)
As a side note: there is a typo in the WP (13.3.1.2 (over.match.oper)
paragraph 7
struct A {
operator int();
};
A operator+(const A&, const A&);
void m() {
A a, b;
a + b; // a.operator+(b) chosen over int(a) + int(b)
}
the "a.operator+(b)" should be "operator+(a, b)".
Chris.
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1995/09/19 Raw View
In article 95Sep18124228@physics2.Berkeley.EDU, chopps@water.emich.edu (Christian E. Hopps) writes:
>
>Before my main question: I use the term ill-formed below because
>that is what the WP used. Is an ambiguous call ill-formed? I am
>not familiar with this term and so I want to make sure the compiler
>is required to issue some error...
A "well-formed" program is one which conforms to the syntax rules, to the
One-Definition Rule, and to those semantic rules which must be diagnosed
if violated. An "ill-formed" program is one which is not well-formed.
a + / b; // ill-formed, invalid syntax
int k = "hello"; // ill-formed, semantic error which must be diagnosed
char *p = 0; // well-formed and entirely valid
*p = 'a'; // well-formed, contains an error which need not
// be diagnosed (dereference of null pointer)
>When figuring out which operator to use is any precedence given to
>operators defined in the class?
No. Class member functions and global functions participate equally in
overload resolution. Scope rules regarding base class members and
members of namespaces apply, however.
>Basically my interpretation of the
>WP of the following situation is that the "function call" is ill-formed.
>
> class A {
> ...
> A(int);
> operator int();
> bool operator ==(A& a);
> ...
> };
>
> void func()
> {
> A a;
> bool result =
> (a == 4); // ill-formed?
>
>The candidate functions are:
>
> bool A::operator==(A& a); // 1
> bool built-in::operator(int, int); // 2
>
>(1) requires a user-defined conversion (A::A(4)) on its second
>argument. (2) requires a user-defined conversion (a.A::operator int())
>on its first argument.
Correct. Neither of the available interpretations of "==" hides the
other, and each has one exact match and one match with user conversions.
Neither function is preferred, creating an ambiguity which must be diagnosed.
>Someone in another newsgroup was inquiring as to whether their
>compiler's selection of the member operator was a bug.
The analysis above is based on what is in the draft standard. In the
past, it was not clear how the built-in operators participated in
overload resolution. The compiler may be operating on a different set of rules.
---
Steve Clamage, stephen.clamage@eng.sun.com
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: Nathan Myers <ncm@netcom.com>
Date: 1995/09/20 Raw View
chopps@water.emich.edu (Christian E. Hopps) wrote:
>When figuring out which operator to use is any precedence given to
>operators defined in the class?
struct A { A(int); operator int(); bool operator== ( A&); };
struct B { B(int); operator int(); bool operator== (const B&); };
struct C { C(int); operator int(); };
bool operator==(const C&, const C&);
void f()
{
A a(0);
a == 3; // OK, int(a) == 3 [!!]
3 == a; // OK, 3 == int(a)
B b(0);
b == 3; // error: b == B(3), or int(b) == 3 ?
3 == b; // OK, 3 == int(b)
C c(0);
c == 3; // error: c == C(3), or 3 == int(c) ?
3 == c; // error: 3 == int(c), or C(3) == c ?
}
I believe the remarks above are correct. (Notice [!!] that leaving
out the "const" in A means that conversion isn't attempted, because the
result of an implicit conversion is const.)
This really argues for avoiding conversion loops, so you don't
have to remember the silly rules; and if you must use a type that
has such a loop, explicitly qualify the arguments so you get the
operation you want.
Nathan Myers
myersn@roguewave.com
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]