The call to foo(true)
in your program is, as you say, clearly ambiguous; furthermore, it is ambiguous according to the algorithm presented in §10.2 and consequently, it should be flagged on use. (Flagging the using
declaration would be incorrect; 10.2(1) clearly states that ambiguous uses of names are flagged on lookup, not on declaration.)
It's interesting to contrast this program with a similar one, which is the subject of a a recognized gcc bug (slightly modified from that bug report to make the parallel clearer):
#include <iostream>
struct A {
static int foo() {return 1;}
static int foo(char) { return 2;}
};
struct B1 : A {
// using A::foo;
};
struct B2 : A {
// using A::foo;
};
struct C : B1, B2 {
// using B1::foo;
// using B2::foo;
};
int main()
{
std::cout << C::foo();
}
The above program is correct; despite the diamond inheritance, foo
is a static member of A
, so it is not ambiguous. In fact, gcc compiles it without trouble. However, uncommenting the two instances of using A::foo
, which does not change anything about either foo
, causes gcc to produce the oddly reduplicated error noted in the bug report. Uncommenting the two using
declarations inside C
, which presumably triggers the other bug which is the subject of this question, then masks the static function
bug and causes the program to compile again.
clang seems to handle all possible variants of this program, for what it's worth.
Finally, note that an explicitly declared foo(bool)
within C
(in the original program) will win out over any foo(bool)
brought into C
's scope by using
declarations. I suspect that both of these bugs are the result of bad bookkeeping while trying to keep track of the various function declarations in each class's scope and their individual provenance (as a sequence of using
declarations and function declarations).
foo
inmain
, but on theusing
s inC
already:ambig.cc:9: error: using declaration 'using B2::foo' conflicts with a previous using declaration
– Karalynnfoo
rather than in line 9 when the ambiguoususing
declaration is made. – Karalynnusing
is about a name, not a specific override. So B1::foo and B2::foo might be different, possibly intersecting, sets of overrides, and the non-shared overrides are fine. Furthermore, despite theusing
, you could override the intersecting overrides with an explicit declaration in C, so there might not be any ambiguity possible. (10.2(1) "Name lookup can result in an ambiguity, in which case the program is ill-formed.") – Bautzenfoo()
, so at that point a diagnostic should be emitted, unless this falls into some "no diagnostic required" case of course. – Glidewell