Trying to make a class
friends with an extern "C"
function, this code works:
#include <iostream>
extern "C" {
void foo();
}
namespace {
struct bar {
// without :: this refuses to compile
friend void ::foo();
bar() : v(666) {}
private:
int v;
} inst;
}
int main() {
foo();
}
extern "C" {
void foo() {
std::cout << inst.v << std::endl;
}
}
But I was very surprised to find that with g++ 4.6.1 and 4.4.4 I have to explicitly write ::
in friend void ::foo();
otherwise the friendship doesn't work. This ::
is only needed when it's extern "C"
though.
extern "C"
and not without it? What about the name lookup rules changes that makes this necessary? I'm stumped. There is probably some rule for this that I can't find.
Syntax of friend functions: To make a function that is declared outside the class “friendly” to that class, we have to declare the function as a friend function, as seen below: class className{ // Other Declarations friend returnType functionName(arg list); };
The friend function is declared using the friend keyword inside the body of the class. Friend Function Syntax: class className { ... .. ... friend returnType functionName(arguments); ... .. ... }
friend is a keyword in C++ that is used to share the information of a class that was previously hidden. For example, the private members of a class are hidden from every other class and cannot be modified except through getters or setters.
Master C and Embedded C Programming- Learn as you goA friend function of a class is defined outside that class' scope but it has the right to access all private and protected members of the class. Even though the prototypes for friend functions appear in the class definition, friends are not member functions.
[n3290: 7.3.1.2/3]:
Every name first declared in a namespace is a member of that namespace. If afriend
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 (3.4.1) or by qualified lookup (3.4.3) 95) this implies that the name of the class or function is unqualified. until a matching declaration is provided in that namespace scope (either before or after the class definition granting friendship). If a friend function is called, its name may be found by the name lookup that considers functions from namespaces and classes associated with the types of the function arguments (3.4.2). If the name in afriend
declaration is neither qualified nor a template-id and the declaration is a function or an elaborated-type-specifier, the lookup to determine whether the entity has been previously declared shall not consider any scopes outside the innermost enclosing namespace. [..]
The innermost enclosing namespace is the anonymous one, and you didn't qualify the function name, so the name is not found.
The namespace need not be anonymous, either.
Note that the extern "C"
in the question is a red herring, as the following also fails for the same reason:
void foo();
namespace {
struct T {
friend void foo();
private: void bar() { cout << "!"; }
} t;
}
void foo() { t.bar(); }
int main() {
foo();
}
/*
In function 'void foo()':
Line 7: error: 'void<unnamed>::T::bar()' is private
compilation terminated due to -Wfatal-errors.
*/
[alternative testcase, adapted from your original code]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With