c++ 我不明白标准中的3.4/2

aydmsdu9  于 2023-05-08  发布在  其他
关注(0)|答案(3)|浏览(156)

我不明白标准中的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()作用域和全局作用域中查找!

qqrboqgw

qqrboqgw1#

为了扩展@JerryCoffin的评论,合格查找的规则是:

3.4.3艾德名称查找[basic.lookup.qual]

3在声明中,声明者id是限定id,在限定id之前使用的名称在定义的命名空间范围内查找;在成员的类或命名空间的作用域中查找限定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
}

Live Example

41ik7eoe

41ik7eoe2#

首先查找::的左侧,然后在其中查找右侧。因此,要查找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,则查找::前面的名称时只考虑专门化为类型的名称空间、类型和模板。如果找到的名称没有指定名称空间或类、枚举或依赖类型,则程序是病态的。

mefy6pfw

mefy6pfw3#

正如dyp在评论中所解释的那样,该段只是解释了在表达式的上下文中查找名称时的含义。它并不是说每个名字都是在表达式的上下文中查找的。因此,为了理解N::i的名称查找是如何工作的,您必须查阅标准的相应部分,该部分可能会告诉您在某些表达式的上下文中查找名称,也可能不会告诉您。
根据C++11 [expr.prim.general]/9:
一个::,或者一个命名空间的 nested-name-specifier(7.3),在任何一种情况下,后跟该命名空间的成员的名称(或者通过 using-directive 使其可见的命名空间的成员的名称)都是一个 qualified-id;3.4.3.2描述了用于出现在qualified-id中的命名空间成员的名称查找。结果是成员。结果的类型就是成员的类型。如果成员是函数或变量,则结果为左值,否则为纯右值。
3.4.3.2 [namespace.qual]进一步解释说:
如果一个 qualified-idnested-name-specifier 指定了一个命名空间,则在该命名空间的作用域中查找在 nested-name-specifier 之后指定的名称。[...]
还有更多但都无关紧要
请注意,这有点循环。[namespace.qual]/1真正应该说的是,当你有一个 * 看起来 * 像 qualified-id 的东西,因为它是一个命名空间的 nested-name-specifier,后跟一个标识符(或者其他可以是 unqualified-id 的东西),你在 nested-name-specifier 之后查找名称,只有当它成功时,整个东西才是一个 qualified-id
无论如何,关键是“在表达式的上下文中查找”在这个特定的例子中是不相关的。

相关问题