Abyx
Abyx

Reputation: 12918

Friend function is not visible in the class

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?

Upvotes: 11

Views: 3498

Answers (4)

Vlad from Moscow
Vlad from Moscow

Reputation: 310990

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;
}

Upvotes: 4

Danvil
Danvil

Reputation: 23001

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
}

Upvotes: 4

Mike Seymour
Mike Seymour

Reputation: 254471

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.

Upvotes: 12

vvv
vvv

Reputation: 53

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

Upvotes: -4

Related Questions