A friend's declaration and the essence that it stands for

I have one question about friend functions / classes. Consider the following code:

#include <iostream>

struct A
{
private:
    int a = 5;
    friend int foo(A a);
};

int foo(A a)
{
    return a.a;
}

int a = foo(A());

int main(){ std::cout << a << std::endl; }

      

DEMO

It works great and both int foo()

within class and global scope refer to the same object. Although the declaration int foo()

within the scope of the class did not inject the name into the global scope. If it were then, we would get a compile-time linker error in the code:

#include <iostream>

struct A
{
private:
    int a = 5;
    friend int foo();
};

int a = foo(); //undeclared foo

int main(){ std::cout << a << std::endl; }

      

DEMO

I cannot find an explanation about this in the Standard. He says that N3797:11.3/6 [class.friend]

:

A function can be defined in a friend's if class declaration, and only if the class is a non-local class (9.8), the function name is unqualified, and the function has a namespace scope.

So this explains why the following code works fine:

#include <iostream>

struct A
{
private:
    int a = 5;
    friend int foo(A a)
    {
        return a.a;
    }
};

int a = foo(A());

int main(){ std::cout << a << std::endl; }

      

DEMO

We defined the function in the friend's declaration and as the standard said it became a member of the global namespace. But the rule covers the defintion , not the declaration. Obviously, no expression is a definition. Therefore, we cannot apply it to the first example.

+3


source to share


1 answer


In the latest program

#include <iostream>

struct A
{
private:
    int a = 5;
    friend int foo(A a)
    {
        return a.a;
    }
};

int a = foo(A());

int main(){ std::cout << a << std::endl; }

      

The compiler finds the function definition foo

only because of the argument-dependent search. You should consider the following section of the C ++ Standard

3.4.2 Finding Argument Dependent Names

2 For each type of argument T in a function call, there is a set of zero or more associated namespaces and a set of zero or more associated classes. The namespace sets and classes are completely defined by the types of the arguments function (and the namespace of any template template argument). Typedef names and use-declarations used to indicate types do not contribute to this set.

Thus, in this program, the compiler searches for the function in the class scope because the function argument is of the class type. If you change the definition of a function, for example, as follows, then the compiler will not find that function.



#include <iostream>

struct A
{
public:
    A( int x ) : a( 2 * x ) {}

private:
    int a;
    friend int foo( int x )
    {
        A a( x );

        return a.a;
    }
};

int a = foo( 10 );


int main() 
{
    std::cout << a << std::endl;

    return 0;
}

      

But if you add a function declaration to the scope where the class is defined, then the compiler will see the function

#include <iostream>

struct A
{
public:
    A( int x ) : a( 2 * x ) {}

private:
    int a;
    friend int foo( int x )
    {
        A a( x );

        return a.a;
    }
};

int foo( int );

int a = foo( 10 );


int main() 
{
    std::cout << a << std::endl;

    return 0;
}

      

Here's the output of the program

20

      

0


source







All Articles