はい、A
3.4.1 による通常の非修飾名ルックアップであり、ネストされた名前指定子を囲むスコープを連続して検索しますが、例外として、クラスと名前空間名のみが検出されます。たとえば、次のようになります。
int main()
{
int X;
X::i = 42; // OK, int X not found.
}
http://ideone.com/NaEIVd
実際にこの抜け穴を使用することはお勧めできません。X
クラス型のオブジェクトだったとしX::i
たら、X.i
まったく別のものになる可能性があります。
標準からこの結論に到達するには、3.4.3 (修飾ルックアップ、最終的に分析する高レベルの構造) から始めます。
クラスまたは名前空間のメンバーまたは列挙子の名前は、そのクラス、名前空間、または列挙を示す入れ子になった名前指定子に :: スコープ解決演算子 (5.1) を適用した後に参照できます。nested-name-specifier の :: スコープ解決演算子の前に decltype-specifier がない場合、:: の前にある名前の検索では、特殊化が型である名前空間、型、およびテンプレートのみが考慮されます。見つかった名前が名前空間、クラス、列挙、または依存型を指定していない場合、プログラムは不適切な形式です。
段落 2 を読むと、qualified-id が宣言されていないため、適用されません。残りの段落も同様に、適用できない例外を指定しています。では、 の前にあるものは何::
ですか? 文法を参照してください。
nested-name-specifier:
::
type-name ::
namespace-name ::
decltype-specifier ::
nested-name-specifier identifier ::
nested-name-specifier templateopt simple-template-id ::
アプリオリな基準にのみ一致しtype-name ::
ます。namespace-name ::
また、これらはこれまでに発見されたものと重複しています。type-name
またはnamespace-name
通常、特定のコンテキストでどのように解決されますか? 修飾されていないルックアップ。3.4.1 に進みます。
まず、3.4.1/1 は心に留めておくべき一般的な規則です。
3.4.1 にリストされているすべてのケースで、スコープは、それぞれのカテゴリのそれぞれにリストされている順序で宣言を検索されます。名前の検索は、名前の宣言が見つかるとすぐに終了します。宣言が見つからない場合、プログラムは不正な形式です。
次に該当する段落は 6 です。
名前空間 N のメンバーである関数の declarator-id に続く関数の定義で使用される名前 (ただし、説明の目的でのみ、N はグローバル スコープを表すことができます) は、ブロック内で使用する前に宣言する必要があります。それが使用されているか、それを囲むブロック (6.3) の 1 つで使用されているか、名前空間 N で使用する前に宣言するか、N がネストされた名前空間の場合は、N の囲んでいる名前空間の 1 つで使用する前に宣言する必要があります。
このルールは、実際にグローバル名前空間で名前を検索するように指示していませんが、リスト内の関数の外側の名前空間 (この場合はグローバル名前空間) について言及しており、段落 1 ではリストされた名前空間を検索するように指示されています。したがって、名前のルックアップを作成するにはこれで十分です。
驚くべきことに、内部の囲まれた名前空間を優先する再帰検索について言及していませんが、実際にはあなたの例にはそのようなものがないので、ここでやめます:) . コンパイルをコンパイラに任せ、問題が発生した場合にのみ手動で作業する方がはるかに高速です。