web-dev-qa-db-ja.com

宣言された友人クラスをクラスで参照できないのはなぜですか?

次のコードはコンパイルされません。

struct X {
  friend class Y;
  Y* ptr;
};

cppreference は、状況を次のように説明します。

...フレンド宣言で使用されるクラスの名前がまだ宣言されていない場合は、その場で前方宣言されます。

「スポット」が友人関係が宣言されている場所を意味する場合、メンバーY* ptr。なぜコンパイルしないのですか?標準のどこでこれが禁止されていますか?

27
Kan Li

これはサイトの間違いです。これは、友好宣言は前方宣言の代替ではないという標準と矛盾しています。

7.3.1.2.3名前空間で最初に宣言されたすべての名前は、その名前空間のメンバーです。非ローカルクラスのフレンド宣言が最初にクラス、関数、クラステンプレート、または関数テンプレートを宣言する場合、フレンドは最も内側にある名前空間のメンバーです。フレンド宣言は、それ自体では、非修飾ルックアップまたは修飾ルックアップに対して名前を表示しません。

非修飾または修飾ルックアップから名前が見えないという部分は、基本的に、名前が前方宣言のように動作しないことを意味します。

29
dasblinkenlight

@dasblinkenlightの答えに加えて、 .3.2宣言のポイントlit. 1 の注記は、フレンド宣言がクラス名を導入しない(したがって、「前方宣言」しない)ことを明示的に示しています。

10 [注:フレンド宣言は、最も近い囲みネームスペースのメンバーである関数またはクラスを参照しますが、そのネームスペースに新しい名前を導入しません([namespace.memdef])。

2
Stephan Lechner

このコードを修正する1つの方法は、単純に add class keyword

struct X {
    friend class Y;
    class Y* ptr;
};

Xがグローバルスコープにある場合、グローバルスコープでclass Yを転送宣言します。

0
Evg