6

C++ 標準 ISO/IEC 14882:2003(E) の 7.3.1.2 名前空間メンバー定義による

名前空間で最初に宣言されたすべての名前は、その名前空間のメンバーです。非ローカル クラスのフレンド宣言が最初にクラスまたは関数を宣言する場合 (これは、クラスまたは関数の名前が修飾されていないことを意味します)、フレンド クラスまたは関数は、最も内側の囲んでいる名前空間のメンバーです。

// Assume f and g have not yet been defined.
void h(int);
template <class T> void f2(T);
namespace A {
   class X {
   friend void f(X);  //  A::f(X) is a friend
      class Y {
         friend void g();  //  A::g is a friend
         friend void h(int);  //  A::h is a friend
         //  ::h not considered
         friend void f2<>(int);  //  ::f2<>(int) is a friend
      };
   };
   //  A::f, A::g and A::h are not visible here
   X x;
   void g() { f(x); }  // definition of A::g
   void f(X) { /* ... */}  // definition of A::f
   void h(int) { /* ... */ }  // definition of A::h
   //  A::f, A::g and A::h are visible here and known to be friends
}

は最初にグローバル名前空間で宣言されているためvoid h(int);、グローバル名前空間のメンバーです。なぜフレンド宣言friend void h(int);はではなくclass Y考慮されるのですか?A::h::h

4

2 に答える 2

2

段落の最後に次のように述べています。

フレンドとして宣言されたクラスまたは関数の前の宣言を探すとき、およびフレンド クラスまたは関数の名前が修飾名でもテンプレート ID でもない場合、最も内側の囲み名前空間の外側のスコープは考慮されません。

::h考慮されないのは、修飾名でもテンプレート ID でもないためです。これは、'::f2` がテンプレート ID であるため、考慮される理由でもあります。

于 2012-12-16T04:53:38.747 に答える
1

内部宣言は、グローバル名前空間の宣言を隠していると思います。また、フレンド宣言自体は前方宣言であるため、それらの関数を単に「参照」するだけでなく、グローバル名前空間内のものを隠します。

N3485 の 3.3.10.1「名前の隠蔽」を参照:

名前は、ネストされた宣言領域または派生クラス (10.2) で同じ名前を明示的に宣言することによって非表示にすることができます。

11.3.4 友達:

フレンド宣言で最初に宣言された関数には、外部リンケージ (3.5) があります。それ以外の場合、関数は以前のリンケージ (7.1.1) を保持します。

3.5.2を見る:

名前に外部リンクがある場合、それが示すエンティティは、他の翻訳単位のスコープまたは同じ翻訳単位の他のスコープからの名前で参照できます。

于 2012-12-16T04:06:12.137 に答える