Reputation: 408
I'm reading C++ Primer and the author says,
"If a class is defined inside a namespace, then an otherwise undeclared friend function is declared in the same namespace:
namespace A {
class C {
public:
friend void f(const C&); // makes f a member of namespace A
};
}
Doesn't it mean that I don't have to declare function f() again inside namespace?
When I simply define function f() outside of namespace as
void
A::f(const C& obj)
{
std::cout << "f(const C&) " << std::endl;
}
I get error from g++ 4.5 saying,
FriendDeclarations1.cpp:40:23: error: ‘void A::f(const A::C&)’ should have been declared inside ‘A’
Can anyone please tell me what does the author imply?
Upvotes: 2
Views: 1436
Reputation: 408
Standard 7.3.1.2 / 3 :
Every name first declared in a namespace is a member of that namespace. If a friend declaration in a non-local class first declares a class or function83) the friend class or function is a member of the innermost enclosing namespace. The name of the friend is not found by simple name lookup until a matching declaration is provided in that namespace scope (either before or after the class declaration granting friendship).
Upvotes: 2
Reputation: 109119
What the author means is that the friend function is implicitly declared within the same class namespace if its namespace is not stated explicitly.
So f
needs to defined within namespace A
#include <iostream>
namespace A {
class C {
friend void f(const C&); // makes f a member of namespace A
int i;
public:
C() : i(42) {}
};
void f(const A::C& obj)
{
std::cout << "f(const A::C&) " << std::endl;
std::cout << "obj.i = " << obj.i << std::endl; // access private member
}
}
int main()
{
A::C ac;
f(ac);
return 0;
}
You can change this behavior by explicitly stating the namespace that f
belongs to
#include <iostream>
// forward declarations
namespace A { class C; }
namespace B { void f(const A::C&); }
namespace A {
class C {
friend void B::f(const C&);
int i;
public:
C() : i(42) {}
};
}
namespace B {
void f(const A::C& obj)
{
std::cout << "f(const A::C&) " << std::endl;
std::cout << "obj.i = " << obj.i << std::endl; // access private member
}
}
int main()
{
A::C ac;
B::f(ac);
return 0;
}
Upvotes: 3
Reputation: 10720
What you have there is interpreted as a class member definition, for a class declaration that looks like this:
class A {
void f(const C& obj);
}
You should define f this way:
namespace A {
void f(const C& obj)
{
std::cout << "f(const C&) " << std::endl;
}
}
Upvotes: 0