Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it legal to friend a function via a using declaration?

The following (LiveWorkspace here) is rejected by GCC 4.7.2, GCC 4.8.0, and ICC 13.0.1.

namespace A {
    namespace B {
        void C();
    }
    using B::C;
}

class D {
    friend void A::C();
};

Additionally, it crashes Clang 3.2 (!). I've submitted a bug report and patch already, for the crash bug, but I'm not 100% sure if this code is really in error, because I can't find anything in §7.3.3 [namespace.udecl] or §11.3 [class.friend] that explicitly addresses this case, but maybe there's something in the definition of one of the various name specifier terms that I've missed.

Furthermore, it seems like all four compilers accept the following (LiveWorkspace here):

namespace A {
    namespace B {
        class C;
    }
    using B::C;
}

class D {
    friend class A::C;
};

There doesn't seem to be anything fundamentally different about these two cases, so I'm curious what GCC and ICC's grounds to reject the first example but not this one are, if any. Can anyone more familiar with the standard find anything that addresses this?

It's definitely a minor issue at best, but since I'm patching it, I'd like to be sure I'm doing the right thing...

EDIT: This is patched now in clang/trunk!

NEW EDIT: Johannes's answer below explains why my original example is rejected, but it doesn't seem to explain why GCC and ICC also reject the following (LiveWorkspace here):

namespace A {
    namespace B {
        void C();
    }
    using B::C;

    class D {
        friend void C();
    };
}
like image 463
Stephen Lin Avatar asked Oct 05 '22 14:10

Stephen Lin


1 Answers

8.3p1:

When the declarator-id is qualified, the declaration shall refer to a previously declared member of the class or namespace to which the qualifier refers (or, in the case of a namespace, of an element of the inline namespace set of that namespace (7.3.1)) or to a specialization thereof; the member shall not merely have been introduced by a using-declaration in the scope of the class or namespace nominated by the nested-name-specifier of the declarator-id.

A class foo; or class foo::bar; does not contain a declarator-id, so it is not affected by this rule. Instead, the foo::bar is part of an elaborated-type-specifier (7.1.6.3).

like image 153
Johannes Schaub - litb Avatar answered Oct 27 '22 00:10

Johannes Schaub - litb