简体   繁体   中英

When is ADL lookup is considered for unqualified dependent name?

I struggle with this example in cpp reference.

I thought ordinary + ADL lookups would produce the following set in both cases: f(char) (ordinary lookup), f(int)/f(E) (ADL lookup as it takes into account visibility from the POI). Then overload resolution would select f(E) in the first case and f(int) in the other case.

Could you please explain to me what exactly happens under the hood (lookup, overload resolution) in this case?

Thanks a lot!

Example sample:

void f(char); // first declaration of f
 
template<class T> 
void g(T t) {
    f(1);    // non-dependent name: lookup finds ::f(char) and binds it now
    f(T(1)); // dependent name: lookup postponed
    f(t);    // dependent name: lookup postponed
//  dd++;    // non-dependent name: lookup finds no declaration
}
 
enum E { e };
void f(E);   // second declaration of f
void f(int); // third declaration of f
double dd;
 
void h() {
    g(e);  // instantiates g<E>, at which point
           // the second and the third uses of the name 'f'
           // are looked up and find ::f(char) (by lookup) and ::f(E) (by ADL)
           // then overload resolution chooses ::f(E).
           // This calls f(char), then f(E) twice
    g(32); // instantiates g<int>, at which point
           // the second and the third uses of the name 'f'
           // are looked up and find ::f(char) only
           // then overload resolution chooses ::f(char)
           // This calls f(char) three times
}

ADL looks for function in the namespace (or class) associated to the type of the argument. So if you declare enum E in a namespace X , ADL will only look-up inside namespace X (see bellow).Fundamental types as int do not have any associated namespace. So ADL for fundamental types never find anything.

void f(char); // first declaration of f
 
template<class T> 
void g(T t) {
    f(1);    // non-dependent name: lookup finds ::f(char) and binds it now
    f(T(1)); // dependent name: lookup postponed
    f(t);    // dependent name: lookup postponed
//  dd++;    // non-dependent name: lookup finds no declaration
}

namespace X {
    enum E { e };
    void f(E);   // second declaration of f
    void f(int); // third declaration of f
    }
double dd;

void f(int);//the global namespace is not associated to fundamental types
 
void h() {
    //The associated scope of X::e is namespace X.
    g(X::e);  // instantiates g<E>, at which point
           // the second and the third uses of the name 'f'
           // are looked up and find ::f(char) (by lookup) and X::f(int) and X::f(E) (by ADL)
           // then overload resolution chooses X::f(E).
           // This calls f(char), then X::f(E) twice

    //Fundamental types do not have any associated namespace
    g(32); // instantiates g<int>, at which point
           // the second and the third uses of the name 'f'
           // are looked up and find ::f(char) only
           // then overload resolution chooses ::f(char)
           // This calls f(char) three times
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM