Igo*_* R. 4 c++ templates language-lawyer name-lookup argument-dependent-lookup
考虑以下:
struct Base {
void foo();
};
template <class T>
struct Derived : Base {
void bar() {
this->foo();
}
};
Run Code Online (Sandbox Code Playgroud)
通常,我们解释了this->使它foo()成为从属名称的原因,因此其查找被推迟到第二阶段,即模板实例化点。
但是第二阶段查找仅调用不考虑成员函数的ADL,对吗?
我很感谢任何指向Standard段落的指针,这些段落解释了为什么上面的代码会编译。
但是第二阶段查找仅调用不考虑成员函数的ADL,对吗?
它不是。但是,ADL将添加到查找集,但它并不包含所有查找集。另外,这里所说的想法适用于in中的postfix-expression postfix-expression(args),当所说的postfix-expression是unqualified-id时。
[温度深度]
1 ...以以下形式表示:
postfix-expression(表达式列表opt)如果postfix-expression是unqualified-id,则在以下情况下,unqualified-id表示从属名称:
- [...特定条件...]
如果运算符的操作数是与类型有关的表达式,则该运算符还表示从属名称。这样的名称不受限制,并且在模板定义的上下文和实例化点的上下文中都在模板实例化的点([temp.point])中进行查找。
因此,如果您在那里foo(),则查找将不考虑成员,而是仅尝试在定义和实例化(假设我们有一个从属表达式的情况下,ADL可以添加到查找集中)中的自由函数。
但是对于this->foo(我有意省略了呼叫,以讨论postfix-expression),我们具有类成员访问权限。在这里,其他段落适用:
[temp.dep.type]
5名称是当前实例的成员,如果它是
- [...]
- 表示类成员访问表达式中的成员的id表达式,其对象表达式的类型是当前实例,并且在查找时,id表达式引用类中的至少一个成员,该成员是当前实例或其非依赖基类。[?注意:如果没有找到这样的成员,并且当前实例具有任何依赖的基类,则id表达式是未知专业化的成员;见下文。?—尾注?]
6名称是未知专业名称的成员,如果它是
- [...]
- 表示类成员访问表达式中的成员的id表达式,其中
- 对象表达式的类型是当前实例,当前实例至少具有一个依赖基类,并且id-expression的名称查找未找到当前实例或非依赖基类的成员其中 要么
7类似地,如果对象表达式的类型为当前实例的类成员访问表达式中的id表达式未引用当前实例的成员或未知专业化的成员,则程序格式错误即使未实例化包含成员访问表达式的模板;无需诊断。
这些项目符号告诉我们this->foo遇到什么情况下要执行的查找。它仅查找成员。在我们的例子中,当前实例中有一个非依赖基类,因此可以毫无疑问地找到该成员。
找到成员函数后,后缀表达式this->foo表示可调用,这就是函数调用的解决方式。