5

以下(ここでは LiveWorkspace)は、GCC 4.7.2、GCC 4.8.0、および ICC 13.0.1 によって拒否されます。

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

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

さらに、Clang 3.2 (!) をクラッシュさせます。クラッシュ バグについては、既にバグ レポートとパッチを提出しましたが、 §7.3.3 [namespace.udecl]または§11.3 [class.friend]で明示的にこのケースに対処していますが、さまざまな名前指定子の用語の 1 つの定義に、私が見逃した何かがあるのか​​もしれません。

さらに、4つのコンパイラすべてが次を受け入れるようです(LiveWorkspace here)

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

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

これらの 2 つのケースについて根本的な違いはないように思われるので、GCC と ICC が最初の例を拒否する根拠が何であるかを知りたいのですが、もしあれば、これはそうではありません。標準に精通している人は、これに対処するものを見つけることができますか?

せいぜいマイナーな問題であることは間違いありませんが、パッチを適用しているので、正しいことをしていることを確認したいと思います...

編集:これはclang/trunkでパッチされました!

新しい編集: 以下の Johannes の回答は、私の元の例が拒否された理由を説明していますが、GCC と ICC が以下も拒否する理由を説明していないようです(LiveWorkspace here) :

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

    class D {
        friend void C();
    };
}
4

1 に答える 1

4

8.3p1:

declarator-id が修飾されている場合、宣言は、修飾子が参照するクラスまたは名前空間 (または、名前空間の場合は、その名前空間のインライン名前空間セットの要素) の以前に宣言されたメンバーを参照する必要があります (7.3 .1)) またはその専門化に; メンバーは、declarator-id のネストされた名前指定子によって指定されたクラスまたは名前空間のスコープ内の using 宣言によって単に導入されたものであってはなりません。

class foo;orにclass foo::bar;は declarator-id が含まれていないため、この規則の影響を受けません。代わりに、foo::bar精巧な型指定子 (7.1.6.3) の一部です。

于 2013-03-28T21:45:57.957 に答える