Topic: Question on overload resolution


Author: Kevin_VanHorn@ndsu.nodak.edu (Kevin S. Van Horn)
Date: Thu, 17 Oct 2002 01:41:50 +0000 (UTC)
Raw View
The following code seems to work, but I have doubts as to whether it
is legal according to the Standard:

----------

struct A { };
struct B : private A { };

struct X {
  X() { }
  X(A) { cout << "Called A ctor" << endl; }
  X(B) { cout << "Called B ctor" << endl; }
  X(X &) { cout << "Called non-const copy ctor" << endl; }
  operator A() const { return A(); }
  operator B() { return B(); }
};

...

X x(X());

----------

The X(X &) ctor cannot be called in the above definition of x, as
temporaries cannot be bound to non-const references.  There are then
two possibilities:
- convert X() to type A and then call X(A) ctor, or
- convert X() to type B and then call X(B) ctor.

Is this ambiguous, or do the C++ overload resolution rules
unambiguously choose one of these two?  If the latter, what are the
relevant paragraphs from the Standard?

---
[ 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: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 17 Oct 2002 08:44:24 +0000 (UTC)
Raw View
Kevin S. Van Horn wrote:
> X x(X());

This declares a function named x which takes a single parameter
of type pointer to function with no parameters which returns X
and returns an X.

---
[ 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: vAbazarov@dAnai.com ("Victor Bazarov")
Date: Thu, 17 Oct 2002 15:02:29 +0000 (UTC)
Raw View
"Hyman Rosen" <hyrosen@mail.com> wrote...
> Kevin S. Van Horn wrote:
> > X x(X());
>
> This declares a function named x which takes a single parameter
> of type pointer to function with no parameters which returns X
> and returns an X.


Actually, according to the Standard, the inner-most parentheses
do not matter and the statement is parsed as

    X x(X);

which, of course, _is_ a function declaration, only it takes an
X as its parameter, not a function pointer (8.2/1).

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


---
[ 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: Kevin_VanHorn@ndsu.nodak.edu (Kevin S. Van Horn)
Date: Thu, 17 Oct 2002 15:02:56 +0000 (UTC)
Raw View
Hyman Rosen wrote:
> Kevin S. Van Horn wrote:
> > X x(X());
>
> This declares a function named x which takes a single parameter
> of type pointer to function with no parameters which returns X
> and returns an X.

Oops, forgot about that particular syntactic booby trap.  OK, let's
repeat the question, replacing that line with

X x((X()));

---
[ 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: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 17 Oct 2002 16:33:38 +0000 (UTC)
Raw View
Kevin S. Van Horn wrote:
> struct A { };
> struct B : private A { };
>
> struct X {
>   X() { } X(A) { } X(B) { } X(X &) { }
>   operator A() const { return A(); }
>   operator B() { return B(); }
> };
>
> X x((X()));
 >
> Is this ambiguous, or do the C++ overload resolution rules
> unambiguously choose one of these two?  If the latter, what are the
> relevant paragraphs from the Standard?

Unambiguous, choosing the B path. 8.5/14/4/2 tells us that x
will be initialized through a constructor. The available ones
are X(A) and X(B), so overload resolution has to decide which
one to call. The operand X() is non-const, so X::operator B
can be called on it directly, while X::operator A would first
require a qualification conversion, so by 13.3.3.2/3/4, the
first one is better, and X() gets converted to B and x is
constructed from that.

---
[ 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: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 17 Oct 2002 16:56:53 +0000 (UTC)
Raw View
Victor Bazarov wrote:
> Actually, according to the Standard, the inner-most parentheses
> do not matter and the statement is parsed as
>     X x(X);
> which, of course, _is_ a function declaration, only it takes an
> X as its parameter, not a function pointer (8.2/1).

I believe you are wrong. If you look at the grammar in 8.1/1,
an empty set of parentheses can only correspond to an empty
parameter declaration list, not to redundant parentheses
around a missing declarator.

If you were correct, it would lead to an unfortunate asymmetry
between 'void f(int(int))' and 'void f(int())'.

---
[ 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: jpotter@falcon.lhup.edu (John Potter)
Date: Thu, 17 Oct 2002 18:01:09 +0000 (UTC)
Raw View
On Thu, 17 Oct 2002 15:02:29 +0000 (UTC), vAbazarov@dAnai.com ("Victor
Bazarov") wrote:

> "Hyman Rosen" <hyrosen@mail.com> wrote...
> > Kevin S. Van Horn wrote:
> > > X x(X());

> > This declares a function named x which takes a single parameter
> > of type pointer to function with no parameters which returns X
> > and returns an X.

> Actually, according to the Standard, the inner-most parentheses
> do not matter and the statement is parsed as

>     X x(X);

> which, of course, _is_ a function declaration, only it takes an
> X as its parameter, not a function pointer (8.2/1).

Look again.  X x(X(a)) is parsed as X x(X a) is X x(X) because of
redundant parens around the a.  However redundant parens are not
allowed around nothing and X x(X()) is parsed as X x(X(*)()) because
it is allowed to omit the (*) in a function pointer parameter.

John

---
[ 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                       ]