Search code examples
c++inner-classesforward-declarationfriend-function

How can I declare a friend function in a namespace that takes an inner class as a parameter?


Consider this code:

namespace foo {}

class A
{
   class B
   {
   };

   friend int foo::bar( B& );
};

namespace foo
{
   int bar( A::B& )
   {
   }
}

G++ 4.4.3 tells me:

friendfun-innerclass.cpp:21: error: 'int foo::bar(A::B&)' should have been declared inside 'foo'

But I can't declare:

namespace foo
{
   int bar( A::B& );
}

before the class A definition because A::B hasn't been declared. And I can't declare "class A::B" obviously, to declare class B I have to give the definition of class A, and as far as I know the "friend" declarations have to be inside the definition of class A.

What's strange to me is that if I take function "bar()" out of namespace foo everything works fine. It seems counterintuitive to me that having a function inside a namespace or not inside a namespace changes whether the compiler will accept a friend function declaration in the class.

Does anybody know of a way to proprerly structure all the declarations and such to get this to work?


Solution

  • Can't be done the way you want to, because you would have to forward declare a nested class (which you can't) in order to provide a prototype for foo::bar.

    As a first attempt to get around this problem, I would probably resort to making foo::bar a function template. That way the compiler will resolve the types after A and B are known.

    Test harness:

    namespace foo
    {
        template<class B> int bar(B&);
    };
    
    class A
    {
       class B
       {
           template<class B> friend int foo::bar( B& );
           int n_;
       public:
           B() : n_(42) {}
       };
    
    public:
        B b_;
    };
    
    template<class B> int foo::bar(B& b)
    {
        return b.n_;
    }
    
    int main()
    {
        A a;
        foo::bar(a.b_);
    }