Unqualified name lookup applied instead of argument-dependent name lookup

╄→尐↘猪︶ㄣ 提交于 2019-12-23 16:34:06

问题


Consider an example from the standard sec 3.4.1/3:

typedef int f;
namespace N 
{
    struct A 
    {
        friend void f(A &);
        operator int();
        void g(A a) 
        {
            int i = f(a);// f is the typedef, not the friend
                         // function: equivalent to int(a)
        }
    };
}

f(a) is postfix expression. How does compiler determine that f(a) is not a function call? I'm wondering when we have no error like f previously declared of typedef int f; as in the following example:

#include <stdio.h>
typedef int foo; //error: previous declaration of ‘typedef int foo’
class B
{
public:
    friend void foo(B b){ printf("3"); } //error: ‘void foo(B)’ redeclared as different kind of symbol

    static const int c=42;
};

int main(){ }

回答1:


(In my version of the C++11 document the example is presented in 3.4.1/3).

The 3.4.1/3 clearly states that for the purposes of parsing, in order to perform the initial determination of whether this is a postfix expression or function call, a usual name lookup is performed. "Usual" means that the lookup is performed as described in the rest of 3.4.1 and no ADL is used at that initial stage. 3.4.1/3 explicitly says that "The rules in 3.4.2 have no effect on the syntactic interpretation of an expression." (3.4.2 is ADL).

In this example, while parsing f(a) the usual lookup is used to look for name f. It finds the global typedef-name ::f and nothing else. This means that f(a) is treated as a postfix expression (a cast), not as a function call. Note, that friend declaration of function f inside A refers to function N::f, but it does not introduce a declaration of N::f into N. Since N::f function is not explicitly declared in N (it is not visible in N), the usual lookup does not see it. It only sees the global ::f, which is a typedef-name.

If you want the usual name lookup to find the function in the first example, you have to declare that function in N explicitly

typedef int f;
namespace N 
{
    struct A;     // <- added
    void f(A &);  // <- added

    struct A 
    {
        friend void f(A &);
        ...

Now the declaration of N::f is visible in N. Now the usual name lookup will find N::f and treat that f(a) as a function call from the very beginning.

Your second example is seriously different from the first. You have no extra namespace there. Because of that the friend function declaration in B refers to the global ::foo and claims that foo is a function. But the global ::foo is already declared as a typedef-name. This contradiction is exactly what causes the error.

(Amusingly, C++03 version of the standard contained an example in 3.4.1/3, which was essentially equivalent to your second example. I.e. the example in the standard was ill-formed. This is reported as Defect #139 of the standard.)



来源:https://stackoverflow.com/questions/23820709/unqualified-name-lookup-applied-instead-of-argument-dependent-name-lookup

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