user803563
user803563

Reputation: 408

Definition of friend function of a class which is inside a namespace.

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

Answers (3)

user803563
user803563

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

Praetorian
Praetorian

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

Tom Kerr
Tom Kerr

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

Related Questions