简体   繁体   中英

ADL and typedefs

In short, I am trying to understand the behavior of Argument-Dependent Lookup in C++. Some statements in ISO/IEC 14882:2017 (E) regarding ADL are not clear to me. I hope somebody would clarify them to me.

According to standard,

Typedef names and using-declarations used to specify the types do not contribute to this set.

and

When considering an associated namespace, the lookup is the same as the lookup performed when the associated namespace is used as a qualifier (6.4.3.2) except that:

  • Any using-directive s in the associated namespace are ignored...

For me, these statements imply that ADL should completely ignore any typedef , or using occurrence. Probably, this is not the case. Consider the following example:

#include <iostream>                                                             

using namespace std;                                                            

namespace N2                                                                 
{
    struct B {};

    template <typename T>                                                       
    void func (const T&) {cout << __PRETTY_FUNCTION__ << endl;}  
};

namespace N                                                                     
{
    typedef N2::B C;             
}                                                                               

void tfunc (N::C) {}                                                     

int main ()                                                     
{                                                                                                                      
    func(tfunc);                                                                 
}

It works, ie, the compiler is able to find func . So, what those quotes from the standard actually mean?

This answer is provided by @IgorTandetnik.

What the standard is saying is that N2 is among the associated namespaces of tfunc , but N is not. In other words, void tfunc (N::C) works exactly the same as void tfunc(N2::B) . If, in your example, you move func to N , it won't be found, despite the fact that, on the surface, the declaration of tfunc mentions N .

Actually, if you just read a bit further down the standard, you can see why your code works. Specifically, N3337 [basic.lookup.argdep]/2 as shown below [emphasis mine]:

The sets of namespaces and classes are determined in the following way:

...

...

If T is a function type , its associated namespaces and classes are those associated with the function parameter types and those associated with the return type .

As you can see, if the argument passed is a function type ( tfunc in your case), types associated with all the parameters ( N2::B is the only type), as well as the return type ( void - fundamental type, so not counted) are considered to create a set of associated namespaces.

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