首页 > 解决方案 > 模板库中的名称查找:我们为什么要添加这个->

问题描述

考虑以下:

struct Base {
    void foo();
};

template <class T>
struct Derived : Base {
    void bar() {
        this->foo();
    }
};

通常,我们解释它this->产生foo()一个依赖名称,因此它的查找被推迟到第二阶段,即模板实例化点。

但是第二阶段查找调用不考虑成员函数的 ADL,不是吗?

我将不胜感激任何指向解释上述代码编译原因的标准段落的指针。

标签: c++templateslanguage-lawyerargument-dependent-lookupname-lookup

解决方案


但是第二阶段查找只调用不考虑成员函数的 ADL,不是吗?

它不是。然而,ADL 添加到查找集中,它并不包含所有这些。此外,您在此处解释的想法适用于 中的后缀表达式postfix-expression(args),当后缀表达式是unqualified-id时。

[温度.dep]

1 ... 在以下形式的表达式中:

后缀表达式(表达式列表选择

如果后缀表达式是一个非限定 ID,则非限定 ID 表示一个从属名称,如果

  • [...具体条件...]

如果运算符的操作数是依赖于类型的表达式,则该运算符也表示依赖名称。此类名称是未绑定的,并且在模板定义的上下文和实例化点的上下文中都在模板实例化点 ([temp.point]) 处查找。

因此,如果您在那里foo(),则查找将不考虑成员,而是仅在定义和实例化点尝试自由函数(假设我们有一个从属表达式,ADL 可以添加到查找集)。

但是对于this->foo(我故意省略了调用,以讨论后缀表达式),我们拥有类成员访问权限。此处适用其他段落:

[温度.dep.type]

5名称是当前实例化的成员,如果它是

  • [...]
  • id-expression 表示类成员访问表达式中的成员,其对象表达式的类型是当前实例化,并且 id-expression 在查找时引用作为当前实例化的类的至少一个成员或其非依赖基类。[ 注意:如果没有找到这样的成员,并且当前实例化有任何依赖的基类,那么 id-expression 是未知特化的成员;见下文。——尾注]

6一个名字是一个未知专业的成员,如果它是

  • [...]
  • 一个 id 表达式,表示类成员访问表达式中的成员,其中任一
    • 对象表达式的类型是当前实例化,当前实例化至少有一个依赖基类,id-expression 的名称查找未找到当前实例化或非依赖基类的类的成员其中;或者

7类似地,如果对象表达式的类型是当前实例化的类成员访问表达式中的 id 表达式不引用当前实例化的成员或未知特化的成员,则程序是非良构的即使包含成员访问表达式的模板没有被实例化;无需诊断。

这些项目符号告诉我们this->foo遇到时要执行的查找。它只查找成员。在我们的例子中,我们在当前实例化中有一个不依赖的基类,因此可以明确地找到该成员。

找到成员函数后,后缀表达式this->foo表示可调用,这就是函数调用的解析方式。


推荐阅读