Friend function is not visible in the class
Asked Answered
D

4

11

I have the following code:

struct M {
    friend void f() {}
    M() {
        f(); // error: 'f' was not declared in this scope
    }
};

int main() {
    M m;
}

Live example

Both g++4.8 and clang3.4 fail to compile it, because f is not visible inside M, or so they say.

However, the Standard gives an example of a similar code

class M {
  friend void f() { } // definition of global f, a friend of M,
                      // not the definition of a member function
};

and says that

A friend function defined in a class is in the (lexical) scope of the class in which it is defined.

(ISO/IEC 14882:2011 11.3 Friends [class.friend] p6, p7)

From this I can't understand how compiler can't find f which is defined in same class where it's used.

It's kinda unlikely that both compilers have the same bug.
So, what did I miss?

Drus answered 8/5, 2014 at 11:42 Comment(1)
Where have you declared it?Pit
C
12

The friend declaration states that a function called f in the surrounding namespace is a friend of the class; but it does not introduce the name f into the namespace. It's not available (except by argument-dependent lookup) until it's been declared in the namespace.

The relevant rule is C++11 7.3.1.2/3:

If a friend declaration in a non-local class first declares a class or function the friend class or function is a member of the innermost enclosing namespace. The name of the friend is not found by unqualified lookup or by qualified lookup until a matching declaration is provided in that namespace scope.

Copy answered 8/5, 2014 at 12:1 Comment(0)
C
4

This quote from the C++ Standard

A friend function defined in a class is in the (lexical) scope of the class in which it is defined.

means the following

9 Name lookup for a name used in the definition of a friend function (11.3) defined inline in the class granting friendship shall proceed as described for lookup in member function definitions.

That is any name used in the function is searched starting from the class scope.

However the function itself is not visible in the namespace until it will be declared outside the class.

So in your case it is enough to declare the function before the class definition

void f() {}

struct M {
    friend void f();
    M() {
        f(); 
    }
};

int main() {
    M m;
}

Or

void f();

struct M {
    friend void f() {}
    M() {
        f(); 
    }
};

int main() {
    M m;
}
Charbonnier answered 8/5, 2014 at 11:59 Comment(3)
@Kate Gregory Thanks. It is a typo due to the operation "copy and paste".Charbonnier
@Jonathan Mee Who did allow you to edit my post?! Do not do this any more!Charbonnier
Aaand... that was my bad. Thanks for catching it.Distortion
V
4

The critical question is under what circumstances is the compiler able/allowed to find your function declaration. For a general friend function, you have to declare it outside of the class such that the compiler is able to find it.

However there is a very useful exception: If the the friend function has an argument of class type, it is able to find the function without additional declaration due to argument-dependent name lookup.

This case is actually very important because normally you would want a friend function to access an object of class type.


Consider the following example:

#include <iostream>

struct M
{
    friend void printI(int a) {
        std::cout << a;
    }
    friend void print(const M& m) { // friend takes object of class type!
        std::cout << "M";
    }
    void foo() {
        printI(2); // ERROR - requires declaration!
        print(*this); // OK!
    }
};

int main()
{
    M m;
    m.foo();
    printI(2); // ERROR - requires declaration!
    print(m); // OK
}
Verity answered 8/5, 2014 at 12:1 Comment(0)
R
-4
struct M {
    friend void f() {}
    M() {
        f(); // error: 'f' was not declared in this scope
    }
};

int main() {
    M m;
}

The above code works perfectly.(tried on DevC++) Also try not to define the function inside the class as it might not have a scope outside it i.e. in main(). In trying to call f() from main() you'll receive an error saying function doesn't exist. Therefore, define function outside classes using :: operator (if necessary) so that there is no problem accessing the function from anywhere. Access friend function defined in class

Raffinate answered 8/5, 2014 at 11:59 Comment(1)
It may work "perfectly" on some ancient, non-compliant compiler, but the question clearly states that it doesn't work on at least two modern compilers.Copy

© 2022 - 2024 — McMap. All rights reserved.