Question

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.

Was it helpful?

Solution

3.4.2/3 Let X be the lookup set produced by unqualified lookup (3.4.1) and let Y be the lookup set produced by argument dependent lookup (defined as follows). If X 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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top