6

I've two question about this code bellow:

namespace A { class window; }

void f(A::window);

namespace A
{
    class window
    {
    private:
       int a;
       friend void ::f(window);
    };
}

void f(A::window rhs)
{
    std::cout << rhs.a << std::endl;
}

1) why do I need to qualify the member function f inside window class to be global by doing ::f(window) ?

2) why do I need to predeclare the function f(A::window) in this particular case, whereas when the class is not defined inside a namespace it's ok for the function to be declared after the function is declared a friend.

jleahy
  • 16,149
  • 6
  • 47
  • 66
AlexDan
  • 3,203
  • 7
  • 30
  • 46

3 Answers3

4

When you declare f() as a friend it's actually done in the enclosing namespace of the containing class (A in this case) if a forward declaration is not already present.

So this...

namespace A
{
    class window
    {
    private:
        friend void ::f(window);
    };
}

essentially becomes this...

namespace A
{
    class window;
    void f(window);

    class window
    {
    private:
        friend void f(window);
    };
}

Edit: Here is a snippet from the C++ standard that explicltly talks about this scenario:

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 nonlocal 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) until a matching declaration is provided in that namespace scope (either before or after the class definition granting friendship).

Community
  • 1
  • 1
Captain Obvlious
  • 19,754
  • 5
  • 44
  • 74
  • So, per the example above, f(window) is treated a member of namespace A ? – Vishnu Pedireddi Jun 07 '12 at 18:08
  • What if f(window) is defined in a namespace of its own say namespace B? Would f(window) belong to namespace A and namespace B ? – Vishnu Pedireddi Jun 07 '12 at 18:57
  • @VishnuPedireddi No, `f(window)` will be declared in namespaces `A` and `B` but only implemented in `B`. Any attempt to access A::f(window) will result in an unresolved linker error. – Captain Obvlious Jun 07 '12 at 19:10
  • @VishnuPedireddi: it's you who will decide which one will belong to. if you did friend void f(window) inside A, then it will belong to A. and if you did friend void B::f(window) inside A, then it will belong to B. so the point is if you did not qualify the function to where it belongs, the compiler assume that the definition of this function will be in the same scope where the class is defined. so you will have an implicite definition assumed by your compiler and wait for the linking time for the definition, which you will get a linking error if you didn't provide one. – AlexDan Jun 07 '12 at 19:12
3

As for 1), your function is not in the namespace, so you must use :: to tell the compiler to search it outside the namespace.

Otherwise, it will only look for function inside the namespace (that's why they exist). Koenig lookup doesn't apply here, as window class is inside the namespace.

not too sure about 2) though, but i bet it is related to 1).

uvgroovy
  • 453
  • 3
  • 9
1

1) because function f is declared and defined outside of the current namespace. If you moved the definition of your class into the same namespace as the function whether global or otherwise you wouldn't need to.

2) you always need to declare a function before it is referenced. Your class references the function with the friend statement.

AJG85
  • 15,849
  • 13
  • 42
  • 50
  • what do you mean by refrences ? what about when the class in not inside any namaespace isn't the same case here ? – AlexDan Jun 07 '12 at 18:03
  • It needs to be able to see the function exists. If the class is in the same namespace as the function definition it may be able to find it but order of declaration matters. This is also why the definition of your function must come after the class declaration as it uses a member from that class. – AJG85 Jun 07 '12 at 18:23
  • Regarding (2), see CaptainObvlious's answer - there is a subtly. AlexDan is not quite correct here. Sometimes, a friend declaration does not need to reference a function declared previously - instead, the friend declaration itself counts as the official declaration of the function, and the function can be defined later. See CaptainObvlious's answer. – Dan Nissenbaum Nov 12 '12 at 05:10