2

According to the standard:

A friend function defined in a class is in the (lexical) scope of the class in which it is defined.

Then why the heck doesn't this work (several versions of GCC tested)?

#include <iostream>
using namespace std;

class A
{
  friend void function() { cout << "text" << endl; };
};

// void function();

int main()
{
  function();
  return 0;
}

Uncommenting the declaration of course solves the problem.

Edit (gcc output):

(xterm) $ g++ -ansi -pedantic -Wall -Wextra test.cpp 
test.cpp: In function ‘int main()’:
test.cpp:13:11: error: ‘function’ was not declared in this scope
Šimon Tóth
  • 35,456
  • 20
  • 106
  • 151

1 Answers1

3

The quote means that the following works - the code is in the lexical scope of the class, such that unqualified name lookup will behave specially

class A
{
  typedef int type;

  friend void function() { 
    type foo; /* type is visible */ 
  };
};

If you had defined "function" in the namespace scope, then "type" would not be visible - you would have to say "A::type". That's why it says in the next sentence "A friend function defined outside the class is not.". Unqualified name lookup for an in-class definition is stated as

Name lookup for a name used in the definition of a friend function (11.4) defined inline in the class granting friendship shall proceed as described for lookup in member function definitions. If the friend function is not defined in the class granting friendship, name lookup in the friend function definition shall proceed as described for lookup in namespace member function definitions.

So the text you quoted is not really required to be normative - the specification of unqualified name-lookup already covers it.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • Oh, you are right I read that wrong, but 11.4.5 still says that it should have namespace scope. – Šimon Tóth Nov 06 '10 at 17:21
  • @Let_Me_be more properly, the text in 11.4/5 should say that the functon is a namespace member. Functions amd objects can't really have scope. Only names of them can have. The Standard is very lax with the terms "scope" and "name", so in many places only the context of the use can tell what is meant. – Johannes Schaub - litb Nov 06 '10 at 17:32
  • For instance when it says that a specific function has a scope, it usually means that it is a member of some namespace (see a similar use at 3.4.2/1 "and namespace-scope friend function declarations (11.4) not otherwise visible may be found."). What makes this worse is that "declaration" can mean two functions: One thing is the introduction of a name, and the other thing is the actual syntactic construct. Only the context can tell what is talked about. – Johannes Schaub - litb Nov 06 '10 at 17:36
  • 1
    @litb "namespace scope" is an established technical term, in C++ it means "file scope". – Šimon Tóth Nov 06 '10 at 17:38
  • For an attempt to clean the use of "scope" up, see http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#554 . Much work is needed to make this end up being clear again, IMO, though. – Johannes Schaub - litb Nov 06 '10 at 17:43
  • @Let_Me_Be yes, "namespace scope" refers to the scope defined by any namespace body. Notably, that includes the scope defined by the entire translation unit (because the entire translation unit is a namespace too), the "global scope". – Johannes Schaub - litb Nov 06 '10 at 17:52
  • OK, anyway, the way it works seems to work is that the function is declared at class scope. That just doesn't seem right. – Šimon Tóth Nov 06 '10 at 17:53
  • BTW we have a similar nick. I'm called "Let_It_Be" :) – Johannes Schaub - litb Nov 06 '10 at 17:54
  • @Let_Me_Be note that this doesn't mean that the friend's name is visible in the class scope. It just says that names visible in class scope are found by unqualified lookup starting at the function (if not hidden by it). This is very useful for friend functions defined in class templates: Outside of the template, you would need to know the template arguments to access the names - inside it you won't. – Johannes Schaub - litb Nov 06 '10 at 17:56
  • @litb OK then, in what scope is the functions name? More precisely, should be. – Šimon Tóth Nov 06 '10 at 18:01
  • @Let_Me_Be, the function will be a namespace member. Whether or not a name is introduced isn't clear from the Standard. Several paragraphs contradict against each other. 3.3/4 says that a "friend declarations (11.4) may introduce a (possibly not visible) name into an enclosing name- space;". 3.3.1/6 says " friend declarations refer to functions or classes that are members of the nearest enclosing namespace, but they do not introduce new names into that namespace". – Johannes Schaub - litb Nov 06 '10 at 18:06
  • @litb Yes, declarations don't, that makes total sense. Definition is a specific case. – Šimon Tóth Nov 06 '10 at 18:10
  • @Let_Me_Be the intersection of this could be: A name is inserted (i.e declared) in the declarative region of the namespace (or equivalently, into the scope defined by that namespace), but the name won't be found during non-ADL lookup unless explicitly declared by a declaration that appears in that namespace. – Johannes Schaub - litb Nov 06 '10 at 18:16
  • Maybe the difference can be better described as introducing a dual nature of "scope": One is the scope of a name, which is the portion of the program code where the name is visible, and the other is the scope itself - i.e the region of program code. The name of the function has no scope - i.e it is invisible. But it is still introduced into some scope (the declarative region of the namespace it is a member of). In this sense, 3.3.1/6 could be changed to say "... but they do not introuce *visible* names into that namespace.". – Johannes Schaub - litb Nov 06 '10 at 18:23