6

How is unqualified name lookup being performed for names using within the friend's function body? Let's consider the following code:

#include <iostream>

void foo();

class A
{
    friend void foo(){ std::cout << a << std::endl; }
    static int a;
};

int A::a = 10;

int main(){ foo(); }

DEMO

The Standard states in the N4296::7.3.1.2/3 [namespace.memdef]:

If a friend declaration in a non-local class first declares a class, function, class template or function template the friend is a member of the innermost enclosing namespace.

So, I expected unqualified name lookup didn't find A::a, but it did. I deliberately put the A::a declaration after the friend's function definition in hope it wouldn't be found. What's the actual rule for the friend's unqualified name lookup?

  • Neat question; I'm *assuming* it has to do with the fact it's a friend, so it's able to access in-scope members of `A` while still be placed in the direct parent's scope. I've never considered this before; interesting find. – Qix - MONICA WAS MISTREATED Apr 11 '15 at 06:04
  • There is no relationship between the `friend` declaration and the `static` member variable. I don't know why you think they are related. – R Sahu Apr 11 '15 at 06:23
  • @RSahu I just asked about unqualified name lookup for stattic data members beacuse We can't use non-ststaic members within friends' function bod directly. –  Apr 11 '15 at 06:32
  • @DmitryFucintv, I understand your question now. Thanks for clarifying. – R Sahu Apr 11 '15 at 06:37
  • @RSahu Since you undersntand my question, maybe you probaly know an answer? –  Apr 11 '15 at 06:48
  • I think that example doesn't apply to the given text. The text says "if ... first declares", but `foo()` is already declared before that. That still doesn't make me any less puzzled as to why the compiler finds the name. Which compiler, btw? – Ulrich Eckhardt Apr 12 '15 at 07:14
  • @UlrichEckhardt This example was compiled with g++ (version 4.9.1 as far as I remember). Yes, I completely agree with your remark, but actually it won't change anything if I put the declaration of foo in the global namespace after the class definition. [Here](http://coliru.stacked-crooked.com/a/0319d9b3636316eb) is an example –  Apr 12 '15 at 07:39
  • Thank you Dmitry. Actually, I asked that before reading your answer below, otherwise I would have been a bit less puzzled, too. – Ulrich Eckhardt Apr 12 '15 at 07:51

1 Answers1

4

The answer was quite simple:

N4296::3.4.1/8 [basic.lookup.unqual] :

For the members of a class X, a name used in a member function body, in a default argument, in an exceptionspecification, in the brace-or-equal-initializer of a non-static data member (9.2), or in the definition of a class member outside of the definition of X, following the member’s declarator-id31, shall be declared in one of the following ways:

[...]

(8.2) — shall be a member of class X or be a member of a base class of X (10.2),

[...]

N4296::3.4.1/9 [basic.lookup.unqual] :

Name lookup for a name used in the definition of a friend function (11.3) defined inline in the class granting friendship shall proceed as described for lookup in member function definitions.

That's it.

UPD:

Inlining is important here. That's why the friend function defined outside the class defintion cannot use static members of the class directly. For instance, the following code pritns compile-time error:

#include <iostream>

class A
{
    static int a;
    friend void foo();
};

int A::a = 10;

void foo(){ std::cout << a << std::endl; }



int main(){ foo(); }

DEMO

Ulrich Eckhardt
  • 16,572
  • 3
  • 28
  • 55