我不明白标准中的 3.4/2:
“在表达式的上下文中查找”的名称在找到表达式的范围内被查找为非限定名称。
如果名称符合条件怎么办,N::i
如下所示?
#include <iostream>
namespace N { int i = 1; }
int main()
{
int i = 0;
std::cout << N::i << '\n';
}
限定名N::i
不在找到的范围内N::i
查找,即不在 main() 的范围和全局范围内查找!
我不明白标准中的 3.4/2:
“在表达式的上下文中查找”的名称在找到表达式的范围内被查找为非限定名称。
如果名称符合条件怎么办,N::i
如下所示?
#include <iostream>
namespace N { int i = 1; }
int main()
{
int i = 0;
std::cout << N::i << '\n';
}
限定名N::i
不在找到的范围内N::i
查找,即不在 main() 的范围和全局范围内查找!
为了扩展@JerryCoffin 的评论,合格查找的规则是:
3.4.3 限定名称查找 [basic.lookup.qual]
3 在 declarator-id 是 qualiified-id 的声明中,在声明的 qualiified-id 之前使用的名称在定义的命名空间范围内查找;qualified-id 后面的名称在成员的类或命名空间的范围内查找。
这是一个例子:
#include <iostream>
struct N { enum { i = 1 }; };
int main()
{
std::cout << N::i << '\n'; // prints 1
struct N { enum { i = 0 }; };
std::cout << N::i << '\n'; // prints 0
}
首先向上查找 的左侧::
,然后在其内部查找右侧。因此,要查找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) 应用于表示其类、命名空间或枚举的嵌套名称说明符之后,可以引用类或命名空间成员或枚举器的名称。如果::
嵌套名称说明符中的范围解析运算符前面没有 decltype 说明符,则查找前面的名称::
仅考虑名称空间、类型和特化为类型的模板。如果找到的名称没有指定命名空间或类、枚举或依赖类型,则程序是非良构的。