最初に の左側を::調べ、次にその中で右側を調べます。したがって、 を検索するN::iには、まずN非修飾検索を使用して検索し、次に内部Nを検索して を検索しますi。単純!
あなたの例では、Nローカルで再定義します。ローカル定義の後、外側の定義は §3.3.10 に従って非表示になります。
コンパイラは、左側 ( N) が型、名前空間、または列挙を生成する必要があることを最初に認識しているため、他の検索結果 (つまり、関数、変数、およびテンプレート) は無視されます。したがって、次のこともできます。
#include <iostream>
struct N { enum { i = 1 }; };
int main()
{
int N = 3;
std::cout << N::i << '\n'; // prints 1
std::cout << N << '\n'; // prints 3
struct N { enum { i = 0 }; };
std::cout << N::i << '\n'; // prints 0
}
http://coliru.stacked-crooked.com/a/9a7c9e34b1e74ce7
§3.4.3/1 を参照:
クラスまたは名前空間のメンバーまたは列挙子の名前は、::スコープ解決演算子 (5.1) がそのクラス、名前空間、または列挙を示すネストされた名前指定子に適用された後に参照できます。nested-name-specifierの::スコープ解決演算子の前に decltype-specifier がない場合、::名前空間、型、および特殊化が型であるテンプレートのみを考慮する前の名前の検索。見つかった名前が名前空間、クラス、列挙、または依存型を指定していない場合、プログラムは不適切な形式です。