Reputation: 12249
struct B {};
struct C : B {};
void f(B){} // worse match than A::f<C>
struct A {
template<class T>
void f(T v) {
f(v); // #1
}
};
int main()
{
A{}.f(C{});
}
Activating ADL lookup in line #1
is as simple as
{
using ::f;
f(v);
}
I think the rule that makes the code fail without the using
directive is:
[basic.lookup.argdep]/3 Let X be the lookup set produced by unqualified lookup and let Y be the lookup set produced by argument dependent lookup (defined as follows). If X contains
- (3.1) a declaration of a class member, or
- (3.2) a block-scope function declaration that is not a using-declaration, or
- (3.3) a declaration that is neither a function nor a function template
then Y is empty. [...]
So, since a call to f
found by non-ADL lookup will find A::f
, which is a class member, overloads found by ADL-lookup are discarded.
Which C++ rule allows to ignore the restriction in 3.1 with the using
declaration, to make the above code compile?
I think I'm completely misunderstanding the context where the rule [basic.lookup.argdep]/3 must be applied, or maybe I have a bigger and hidden hole in my understanding of the name lookup process.
Upvotes: 3
Views: 403
Reputation: 60979
First paragraph on unqualified name lookup:
In all the cases listed in [basic.lookup.unqual], the scopes are searched for a declaration in the order listed in each of the respective categories; name lookup ends as soon as a declaration is found for the name.
For the members of a class
X
, a name used in a member function body […], following the member's declarator-id, shall be declared in one of the following ways:
before its use in the block in which it is used or in an enclosing block ([stmt.block]), or
shall be a member of class
X
or be a member of a base class ofX
([class.member.lookup]), or ...
A local (re)declaration of a name is prioritised and shadows all extrinsic declarations.
Upvotes: 5