St.Antario
St.Antario

Reputation: 27395

Looking for a prior declaration, introduced by friend declaration

There is a quote from 3.4.1/7:

When looking for a prior declaration of a class or function introduced by a friend declaration, scopes outside of the innermost enclosing namespace scope are not considered;

Can you get an example to demonstrate this rule?

Upvotes: 1

Views: 65

Answers (2)

Danvil
Danvil

Reputation: 23011

This rule regulates where the compiler is looking for functions or classes marked as friend. It regulates, that the compiler will only check functions or classes in the same namespace as the class which allows friend access. It will not check functions or classes in other or outer namespaces.


This code will produce an error:

#include <iostream>

namespace a {
  class Q { int x; friend void foo(Q q); };
}

// function foo is in outer namespace (not in a)
void foo(a::Q q) { std::cout << q.x << std::endl; }
//                              ^^^ ERROR q.x is private

int main() {
    a::Q q;
    foo(q);
}

The reason is that the function foo is not in the namespace a, but in an outer namespace (in this case the global namespace). Thus foo does not match the friend declaration in Q.


This code will work:

#include <iostream>

namespace a {
  class Q { int x; friend void foo(Q q); };
}

// function foo is in same namespace as Q
namespace a {
  void foo(Q q) { std::cout << q.x << std::endl; }
//                            ^^^ OK access allowed by friend
}

int main() {
    a::Q q;
    a::foo(q);
}

This works because the function foo is now in the same namespace as Q. Thus foo matches the friend declaration in Q.

Upvotes: 1

SingerOfTheFall
SingerOfTheFall

Reputation: 29966

Sure. This code works (both classes are in the same namespace):

namespace Foo {
  class Bar
  {
  friend class FooBar;
  public:
    Bar() : i(0){}
  private:
    int i;
  };

  class FooBar
  {
    FooBar( Bar & other )
    {
      other.i = 1;
    }
  };
}//namespace Foo

And this code fails (the friend class is outside of the Foo's enclosing namespace, thus the lookup fails and you see the the int Foo::i is private within this context error):

namespace Foo {
  class Bar
  {
  friend class FooBar;
  public:
    Bar() : i(0){}
  private:
    int i;
  };
}//namespace Foo

class FooBar
{
    FooBar( Foo::Bar & other )
    {
        other.i = 1;//Oops :'(
    }
};

Upvotes: 1

Related Questions