Why does friend function found successfully via ADL

限于喜欢 提交于 2019-12-06 09:40:30

问题


Consider the following code:

#include <stdio.h>

class A
{
public:
    friend void foo(A a){ printf("3\n"); }
};

int main()
{ 
    foo(A());
}

It works. But I thought that this code is invalid. It is because 3.4.1/3:

For purposes of determining (during parsing) whether an expression is a postfix-expression for a function call, the usual name lookup rules apply.

Usual name lookup rules could not find the friend function because name declared by friend is invisible in the global namespace in my case. Actually 3.3.1/4:

friend declarations (11.3) may introduce a (possibly not visible) name into an enclosing namespace

This implies that the programm is ill-formed. It is because that there is no name which found during the determining is the expression foo(A()); is a postfix-expression for a function call.

I'm confusing...


回答1:


When parsing the following program

#include <iostream>
using namespace std;

typedef int foo;

class A
{
public:
   operator int(){
    return 42;
   }
};

int main()
{ 
    cout << foo(A());
}

the output will be 42 because 3.4.1/3

For purposes of determining (during parsing) whether an expression is a postfix-expression for a function call, the usual name lookup rules apply.

that means: to determine if foo is a postfix-expression (e.g. a cast) or a function call, the compiler will first use name lookup and search for it in the global namespace and/or enclosing scopes / base classes (or with fully qualified lookups if available).

Now take this code:

#include <iostream>
using namespace std;

class A
{
public:
   friend int foo(A a){ return 55; }

   operator int(){
    return 42;
   }
};

int main()
{ 
    cout << foo(A());
}

The above will output 55 thanks to ADL: foo will be found by searching inside the scopes defined by its potential arguments, i.e. A.

A friend declaration introduces a (possibly not visible) name as you posted (3.3.1/4)

friend declarations (11.3) may introduce a (possibly not visible) name into an enclosing namespace

that means the following code will not work

#include <iostream>
using namespace std;

class A
{
public:
   friend int foo(A a){ return 55; }

   operator int(){
    return 42;
   }
};

int main()
{ 
    cout << ::foo(A()); // Not found
    cout << A::foo(A()); // Not found
}

You might want to search for "friend name injection" and/or the Barton-Nackman trick. Short story: now ordinary lookups can't find friend declarations.

So the code you posted is well-formed because ADL allows it to run as I explained in the previous passages.



来源:https://stackoverflow.com/questions/23831077/why-does-friend-function-found-successfully-via-adl

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!