C ++ normal search versus argument dependent

Considering this example described at http://en.cppreference.com/w/cpp/language/adl :

namespace A {
      struct X;
      struct Y;
      void f(int);
      void g(X);
}

namespace B {
    void f(int i) {
        f(i);   // calls B::f (endless recursion)
    }
    void g(A::X x) {
        g(x);   // Error: ambiguous between B::g (ordinary lookup)
                //        and A::g (argument-dependent lookup)
    }
    void h(A::Y y) {
        h(y);   // calls B::h (endless recursion): ADL examines the A namespace
                // but finds no A::h, so only B::h from ordinary lookup is used
    }
}

      

I am wondering why there is ambiguity, since ADL rules are ignored if

"a search set generated by a normal unqualified search contains any of the following."

Here B :: g can be found by unqualified lookup as described in http://en.cppreference.com/w/cpp/language/unqualified_lookup thanks to the rule

For a name used in a function definition, either in its body or as part of a default argument, where the function is a member of a user-declared or global namespace, the block that uses that name is searched before using the name, then the nested block is searched before the start of this block, etc. until it reaches the block, which is the body of the function. The namespace in which the function is declared is then searched until the definition (not necessarily declaration) of the function that uses that name, then the enclosing namespaces, and so on.

Then my question is, why are ADL rules considered in this case?

+3


source to share


2 answers


Full quote

First, argument-dependent searches are ignored if the search set generated by a normal unconditional search contains any of the following:

  • class member declaration
  • function declaration in block scope (this is not a use declaration)
  • any declaration that is not a function or a function template (for example, a function object or other variable whose name conflicts with the name of the function you are looking for)


This means that ADL is only ignored when an unqualified search produces one of three results. Since we are not dealing with a class member, the function is declared in the namespace scope, not the block scope, and we only find the functions that we continue and use ADL.

+6


source


why is ADL rules (argument dependent) considered in this case?

Because there might be better matches in the respective namespaces. For example:.

void f(void*);

namespace A {
struct X;
void f(X*);
}

int main() {
    A::X* x = 0;
    f(x); // A::f is the best match.
}

      



This mechanism is often used for swap

function
:

std::swap

can be namespace-specialized std

for user-defined types, but such specializations are not detected by ADL (namespace is std

not an associated namespace for a user-defined type). The expected way to make a custom type swappable is to provide a non-member function replacement in the same namespace as the type . For details, see the Replaceable Capabilities section.

Any lvalue or rvalue of this type can be replaced with any lvalue or rvalue of a different type using an unqualified function call swap()

in a context where both std::swap

custom and custom ones are visible swap()

.

+1


source







All Articles