Friend declaration in namespace: forward declaration or elaborated type specifier

163 views Asked by At

The following code is successfully compiled by Visual C++ 2013 and 2015 however gcc and clang reports a error. I wonder if C++11 standard has something applicable to this case besides the quote below that allows some ambiguity in treatment of friend class declaration or it is just a VC bug.

The line in question is friend class declaration.

class Friend {
public:
    Friend();
};

void globalFun();

namespace { // Does not matter if it is not anonymous.
    class InNamespace {
        // "friend Friend" or "friend class ::Friend" works in gcc and clang.
        friend class Friend; // <- ???
        friend void ::globalFun(); // Even VC does not allow unqualified name
        class Private {};
    };
}

Friend::Friend() {
    InNamespace::Private a;
    (void) a;
}

void globalFun() {
    InNamespace::Private a;
    (void) a;
}

int main() {
    Friend f;
    globalFun();
    return 0;
}

gcc and clang complains that InNamespace::Private is private in the scope of Friend constructor. It sounds reasonable since Friend is declared at the global namespace that is not innermost enclosing namespace for InNamespace and C++11 standard states

7.3.1.2 Namespace member definitions [namespace.memdef]

3 ... 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.

The same wording in C++14, and in the section 10.3.1.2 of C++17.

I am confused by that in respect to function Visual Studio follows the quoted sentence but it has relaxed rules for the class. It looks like the latter is treated as elaborated type specifier instead of forward declaration of the class within the anonymous namespace. Is there another section of C++ standard that may be considered as permission of name lookup outside of innermost enclosing namespace?

0

There are 0 answers