Mitsuru Kariya
Mitsuru Kariya

Reputation: 948

friend class declaration and using directive

Is the following example well-formed?

namespace N {
    class A;
}
using namespace N;

class B {
    int i;
    friend class A;
};

namespace N {
    class A {
        B m;
        int get() { return m.i; }
    };
}

This example compiled successfully with Clang 3.5, but failed with g++ 4.8.1 with the following:

main.cpp: In member function ‘int N::A::get()’:
main.cpp:7:9: error: ‘int B::i’ is private
     int i;
         ^
main.cpp:14:30: error: within this context
         int get() { return m.i; }
                              ^

C++11 standard §7.3.1.2 p3 says,

If the name in a friend declaration is neither qualified nor a template-id and the declaration is a function or an elaborated-type-specifier, the lookup to determine whether the entity has been previously declared shall not consider any scopes outside the innermost enclosing namespace.

In example, class A is not member of innermost enclosing namespace (i.e. global namespace), but class A is introduced by using directive into global namespace.

Upvotes: 13

Views: 411

Answers (2)

user2249683
user2249683

Reputation:

While using namespace N is pulling the name N::A into the global namespace, it is not declaring that A in the global namespace. Hence an additional A in the global namespace is the friend of B. clang is wrong.

Upvotes: 1

Dietmar Kühl
Dietmar Kühl

Reputation: 154045

To make N::A without qualification a friend of B you'd use

friend A;

rather than

friend class A;

When using an elaborated type specifier, i.e., class A, and it is in this specific form, it introduces a class name (see 3.4.4 [basic.lookup.elab] paragraph 2).

Upvotes: 9

Related Questions