struct A { int x(); };
struct B : A { };
struct C : A { };
struct D : B, C {
using A::x;
int x(double);
void f();
};
void D::f() {
x(1.0); //error in gcc v4.4.0, No match for
'A::x(double)'
}
int main() { }
Isn't there a D::x(double)? I would appreciate if someone could
explain the error message.
Thanks,
Jason
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Poor compiler-diagnostic, I guess. There *is*
D::x(double), but the primary problem is, that the
using-declaration is ambiguous, because there are
two possible A::x: One via base class B, and one
via base class C.
You should either omit the using-declaration from
D or you should pick either B::x or C::x via such
a using-declaration.
HTH & Greetings from Bremen,
Daniel Krügler
The compiler could be confused because there are actually two A::x
functions, one in B and one in C.
Another compiler complains about that:
Comeau C/C++ 4.3.3 (Oct 25 2003 12:02:26) for MS_WINDOWS_x86
Copyright 1988-2003 Comeau Computing. All rights reserved.
MODE:strict errors C++
"X:\reference\quick_test.cpp", line 5: error: "A::x" is ambiguous
using A::x;
^
Bo Persson
You explicitly say 'using A::x', also you only declared D::x(double),
you did not define it so you would get an undefined reference after
removing the 'using' keyword.
> It is normal that a function in derived class hides one in a base
> class. But, I could explain to myself how a base function could hide
> one in a derived class. Here is an example:
>
> struct A { int x(); };
> struct B : A { };
> struct C : A { };
> struct D : B, C {
> using A::x;
> int x(double);
>
> void f();
> };
>
> void D::f() {
> x(1.0); //error in gcc v4.4.0, No match for
> 'A::x(double)'
> }
>
> int main() { }
>
> Isn't there a D::x(double)? I would appreciate if someone could
> explain the error message.
>
I believe that there is nothing wrong with this code and it's a GCC bug.
Clang also compiles this fine. The using declaration overloads the function-
declaration in D. And "x(1.0)" will select "x(double)" of D. It would error
out if you would call "x();" only. Notice that the using declaration itself
is fine, because "A::x" refers to the member x of A, which is not in an
ambiguous subobject of A. Only when selected, the rules added by N1626 to
5.2.5p4 make it ambiguous (i believe the behavior was not specified by
C++03):
"If E2 is a non-static data member or a non-static member function, the
program is ill-formed if the class of which E2 is directly a member is an
ambiguous base (10.2) of the naming class (11.2) of E2."
(the naming class is D, and the class which x is directly a member of is A).
Notice that the new name-lookup introduced by that paper for C++0x changes
some behavior that is nowadays ill-formed, which might be interesting in
this context:
struct A { int x(); };
struct B : A { };
struct C : A { };
struct E : B, C { };
struct D : E {
using E::x;
int x(double);
void f();
};
This using-declaration is ill-formed currently, because "E::x" will find x
in two distinct subobjects and inherently cause an ambiguous lookup result.
The more logical behavior of C++0x makes this fine aswell, because the
lookup will resolve E::x to A's declaration of x. Only once called, the
result is an ambiguity by 5.2.5p4.
By a literate interpretation of 10.2/2 in C++03, we could also go another
route. Notice that there is DR #39 which cites
"Each of these declarations that was introduced by a using-declaration is
considered to be from each sub-object of C that is of the type containing
the declaration designated by the using-declaration."
If we applied this to the lookup of "x" in "D", we would end up with "x" in
B->A, C->A and D: We would have found it in distinct subobjects and get an
ambiguity, at least this is what the DR says (using a similar example). I
don't understand how they come to that conclusion. There is wording
immediately preceeding the quoted text:
"A member name f in one sub-object B hides a member name f in a sub-object A
if A is a base class sub-object of B. Any declarations that are so hidden
are eliminated from consideration."
Since x in D hides C->A and B->A, we will not get an ambiguity, but end up
only finding the x in D. However, i fail to see the utility of considering
"x" to be of "A" for anything else than hiding base-class names relative to
the class where the using declaration appears in. I.e the "using A::x" would
hide C::x and D::x, but "D::x" should not hide "using A::x" - so we
shouldn't apply that rule, even tho a literate interpretation would force
that. In any case, without the literate and with the literate
interpretation, i can't see how compilation of the code would fail.
A g++ dev snapshot[*] also compiles it fine (even with max warnings and
pickiness enabled), which does seem to suggest it's a gcc bug...
[*] g++ (Debian 20100711-1) 4.6.0 20100711 (experimental) [trunk revision 162057]
-Miles
--
Justice, n. A commodity which in a more or less adulterated condition the
State sells to the citizen as a reward for his allegiance, taxes and personal
service.