Reputation: 6390
I reproduce below the argument-dependent lookup (ADL) example given in pages 396 and 397 of Stroustrup book (4th edition):
namespace N {
struct S { int i; };
void f(S);
void g(S);
void h(int);
};
struct Base {
void f(N::S);
};
struct D : Base {
void mf(N::S);
void g(N::S x)
{
f(x); // call Base::f()
mf(x); // call D::mf()
h(1); // error: no h(int) available
}
};
What the comments say above is correct (I've tested it), but that doesn't seem to agree with what the author says in the next paragraph:
In the standard, the rules for argument-dependent lookup are phrased in terms of associated namespaces (iso §3.4.2). Basically:
- If an argument is a class member , the associated namespaces are the class itself (including its base classes) and the class's enclosing namespaces.
- If an argument is a member of a namespace, the associated namespaces are the enclosing namespaces.
- If an argument is a built-in type, there are no associated namespaces.
In the example, x
, which has type N::S
is not a member of class D
, nor of its base Base
. But it's a member of namespace N
. According to the second bullet above, the function N::f(S)
should be the one called, instead of Base::f()
.
The result above also doesn't seem to agree with the second bullet in paragraph 3.4.2p2 in the Standard, which says:
If T is a class type (including unions), its associated classes are: the class itself; the class of which it is a member, if any; and its direct and indirect base classes. Its associated namespaces are the namespaces of which its associated classes are members. Furthermore, if T is a class template specialization, its associated namespaces and classes also include: the namespaces and classes associated with the types of the template arguments provided for template type parameters (excluding template template parameters); the namespaces of which any template template arguments are members; and the classes of which any member templates used as template template arguments are members.
Upvotes: 3
Views: 418
Reputation: 52621
3.4.2/3 Let
X
be the lookup set produced by unqualified lookup (3.4.1) and letY
be the lookup set produced by argument dependent lookup (defined as follows). IfX
contains
- a declaration of a class member, or
- a block-scope function declaration that is not a using-declaration, or
- a declaration that is neither a function or a function template
then Y is empty. Otherwise...
So basically, ADL doesn't kick in when the ordinary lookup finds a member function or local (block-scope) function declaration (or something that's not a function). It does kick in when the ordinary lookup finds a stand-alone namespace-scope function, or when it finds nothing at all.
Upvotes: 4