[namespace.qual] はかなり単純です。
1修飾 IDの入れ子になった名前指定子が名前空間を指定する場合 (入れ子になった名前指定子がである場合、つまり、グローバル名前空間を指定している場合を含む)、入れ子になった名前指定子の後に指定された名前が検索されます。名前空間のスコープ内。template-idのtemplate-argument内の名前は、postfix-expression全体が発生するコンテキストで検索されます。::
2 名前空間X
と namem
の場合、名前空間で修飾されたルックアップ セット S( , )はX
次のm
ように定義されます。S 0 ( , ) が空でない場合、S( , ) は S 0 ( , ) です。それ以外の場合、S( , ) は、 inの using ディレクティブによって指定されたすべての名前空間 N iとそのインライン名前空間セットの S(N i , ) の和集合です。X
m
m
X
X
X
m
X
m
X
m
X
m
m
X
3指定X::m
(X
はユーザー宣言の名前空間) または指定::m
(X
はグローバル名前空間) で、S( X
, m
) が空のセットの場合、プログラムの形式は正しくありません。それ以外の場合、S( X
, m
) がちょうど 1 つのメンバーを持っている場合、または参照のコンテキストがusing 宣言(7.3.3) である場合、S( X
, m
) は の宣言の必須セットですm
。それ以外の場合、 S( , )m
から一意の宣言を選択できるように使用されていない場合、プログラムの形式が正しくありません。X
m
::foo
は、nested-name-specifierを持つ修飾 IDであるため、名前はグローバル スコープで検索されます。 ::
foo
S 0 ( ::
, ) には、名前空間に他の宣言がなく、インライン名前空間がないfoo
ため、単一の宣言が含まれています。S 0 ( , ) は空ではないので、S ( , ) は S 0 ( , ) です。( S 0 ( , ) は空ではないため、 using ディレクティブによって指定された名前空間は調べられないことに注意してください。)namespace foo
foo
::
foo
::
foo
::
foo
::
foo
S( ::
, foo
) には要素が 1 つしかないため、その宣言は に使用され::foo
ます。
::foo::baz
したがって、名前は名前空間を指定するネストされた名前指定子を持つ修飾 IDです。ここでもin namespaceの宣言が 1 つあるため、名前は宣言を参照します。 ::foo
baz
::foo
::foo::baz
class baz
GCC 6+ で観察される動作は、実際にはGCC PR 71173として提出されたバグです。
編集:foo::baz
グローバルスコープで表示されるときのルックアップ、ラ:
foo::baz bang;
foo
最初に非修飾名として を検索する必要があります。[basic.lookup.qual]/1 は、このルックアップが「特殊化が型である名前空間、型、およびテンプレート」のみを参照することを示しています。[basic.scope.namespace]/1 は、名前空間のメンバーとそのスコープについて教えてくれます。
namespace-definitionの宣言領域は、そのnamespace-bodyです。名前空間本体で宣言されたエンティティは、名前空間のメンバーと呼ばれ、これらの宣言によって名前空間の宣言領域に導入された名前は、名前空間のメンバー名と呼ばれます。名前空間のメンバー名には、名前空間のスコープがあります。その潜在的なスコープには、名前の宣言時点からの名前空間が含まれます。また、メンバーの名前空間を指定する各using ディレクティブについて、メンバーの潜在的なスコープには、メンバーの宣言ポイントに続くusing ディレクティブの潜在的なスコープの部分が含まれます。
[basic.lookup.unqual]/4 は、 の宣言namespace foo
が可視であることを示しています。
関数、クラス、またはユーザーが宣言した名前空間の外側で、グローバル スコープで使用される名前は、グローバル スコープで使用する前に宣言する必要があります。
そしてパラ2はそれclass foo
がここにも見られると言います:
using-directiveによって指定された名前空間からの宣言は、 using- directiveを囲む名前空間で可視になります。7.3.4 を参照。3.4.1 で説明されている非修飾名ルックアップ規則のために、using ディレクティブによって指定された名前空間からの宣言は、その囲んでいる名前空間のメンバーと見なされます。
異なる名前空間からの異なるエンティティの 2 つの宣言foo
が見つかったため、[namespace.udir]/6 は、の使用foo
が不適切であることを示しています。
名前検索で 2 つの異なる名前空間で名前の宣言が検出され、宣言が同じエンティティを宣言せず、関数も宣言されていない場合、その名前の使用は不適切です。
foo::baz
に到達する前に、ダイの名前を検索しbaz
ます。