Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Forward Declaration and Friendship in Namespace

According to 7.3.1.2 Namespace member definitions in C++ Standard ISO/IEC 14882:2003(E)

Every name first declared in a namespace is a member of that namespace. If a friend declaration in a non-local class first declares a class or function (this implies that the name of the class or function is unqualified) the friend class or function is a member of the innermost enclosing namespace.

// Assume f and g have not yet been defined.
void h(int);
template <class T> void f2(T);
namespace A {
   class X {
   friend void f(X);  //  A::f(X) is a friend
      class Y {
         friend void g();  //  A::g is a friend
         friend void h(int);  //  A::h is a friend
         //  ::h not considered
         friend void f2<>(int);  //  ::f2<>(int) is a friend
      };
   };
   //  A::f, A::g and A::h are not visible here
   X x;
   void g() { f(x); }  // definition of A::g
   void f(X) { /* ... */}  // definition of A::f
   void h(int) { /* ... */ }  // definition of A::h
   //  A::f, A::g and A::h are visible here and known to be friends
}

Since void h(int); is first declared in the global namespace, it is a member of the global namespace. Why does the friend declaration friend void h(int); in class Y consider A::h rather than ::h?

like image 438
user571470 Avatar asked Dec 16 '12 02:12

user571470


2 Answers

At the end of the paragraph it states:

When looking for a prior declaration of a class or a function declared as a friend, and when the name of the friend class or function is neither a qualified name nor a template-id, scopes outside the innermost enclosing namespace are not considered.

This is why ::h is not considered: It is neither a qualified name nor a template-id. This is also why '::f2` is considered, because it is a template-id.

like image 124
Vaughn Cato Avatar answered Sep 20 '22 12:09

Vaughn Cato


I think the inner declarations shadow the ones in the global namespace. Also, the friend declarations themselves are forward declarations, so they shadow the ones in the global namespace, and not just "refer" to those functions.

Referring to 3.3.10.1 "Name hiding" in N3485:

A name can be hidden by an explicit declaration of that same name in a nested declarative region or derived class (10.2).

11.3.4 Friends:

A function first declared in a friend declaration has external linkage (3.5). Otherwise, the function retains its previous linkage (7.1.1).

Looking at 3.5.2:

When a name has external linkage , the entity it denotes can be referred to by names from scopes of other translation units or from other scopes of the same translation unit.

like image 42
Alexander Kondratskiy Avatar answered Sep 21 '22 12:09

Alexander Kondratskiy