模板库中的名称查找:为什么我们要添加这个>
Name lookup in template base: why do we add this->
考虑以下内容:
struct Base {
void foo();
};
template <class T>
struct Derived : Base {
void bar() {
this->foo();
}
};
通常,我们解释this->
使foo()
成为一个依赖名称,因此它的查找被推迟到第二阶段,即模板实例化点。
但是第二阶段查找只调用ADL,它不考虑成员函数,是吗?
如果有任何指向标准段落的指针,我将不胜感激,它解释了为什么要编译上面的代码。
但是第二阶段查找只调用ADL,它不考虑成员函数,是吗?
没有。然而,ADL添加到查找集,但它并不包括所有查找集。此外,您在这里转述的想法适用于postfix-expression(args)
中的后缀表达式,当所述后缀表达式是不合格id时。
[temp.dep]
1。。。在形式的表达式中:
后缀表达式(表达式列表opt)其中后缀表达式是不合格的id如果,则表示从属名称
- […具体条件…]
如果运算符的操作数是依赖于类型的表达式,则运算符还表示从属名称。此类名称未绑定在中查找模板实例化的点([temp.point])模板定义的上下文和实例化点。
因此,如果您有foo()
,查找将不考虑成员,而是只尝试自由函数,无论是在定义还是实例化时(ADL可以添加到查找集,假设我们有一个依赖表达式)。
但是对于this->foo
(为了讨论后缀表达式,我故意省略了调用),我们有类成员访问权限。其他段落适用于此:
[温度依赖类型]
5如果名称是,则它是当前实例化的成员
- […]
- id表达式表示类成员访问表达式中的成员,对象表达式的类型是当前实例化,并且当查找时,id表达式指的是作为当前实例化的类或其非依赖基类的至少一个成员。[注意:如果没有找到这样的成员,并且当前实例化有任何依赖基类,那么id表达式是未知专门化的成员;请参见下文。—尾注]
6如果名称是,则它是未知专业化的成员
- […]
- 一个id表达式,表示类成员访问表达式中的成员,其中
- 对象表达式的类型是当前实例化,当前实例化至少有一个依赖基类,并且名称id表达式的查找找不到属于当前实例化或其非依赖基类;或
7类似地,如果对象表达式的类型为当前实例化的类成员访问表达式中的id表达式没有指代当前实例化的成员或未知专业化的成员,则即使包含成员访问表达式的模板没有实例化,程序也是格式错误的;无需诊断。
这些项目符号告诉我们遇到this->foo
时要执行什么查找。它只查找成员。在我们的例子中,我们在当前实例化中有一个非依赖基类,所以在那里可以明确地找到成员。
找到成员函数后,后缀表达式this->foo
表示一个可调用函数,这就是函数调用的解析方式。
短语"两阶段查找"被广泛误解,甚至在专家中也是如此。C++17表示两个
这些名称是未绑定的,并且在模板定义的上下文和实例化点的上下文中的模板实例化点(17.6.4.1)处查找。
(在[温度dep]/1中)和
在解析依赖名称时,会考虑来自以下来源的名称:
-在模板定义点可见的声明
-来自与函数参数类型相关联的命名空间的声明实例化上下文(17.6.4.1)和定义上下文。
(在[temp.dep.res]/1中),每一个似乎都表明这是两个阶段。然而,解释这个(非官方)短语的更好方法是,查找是完成的
- 来自模板定义:用于非依赖名称
- 在实例化期间:来自定义,但也仅通过ADL,来自实例化上下文
当解析模板定义时,前一个可以完成,但不需要对不可实例化的模板([temp.res]/8)进行诊断。请注意,后者包括ADL。
有关措辞最近已得到澄清;它现在只说
[注意:对于使用关联命名空间([basic.lookup.argdep])的查找部分,在模板实例化上下文中找到的函数声明通过此查找找到,如[basic.lookup.argdep]中所述。--结束注释]
提醒注意第二阶段的差异。尽管如此,令人困惑的是,它使用依赖名称只是指代不合格的依赖名称/运算符([temp.dep]/2)。像Derived::foo
(来自this->
)这样的名称显然是依赖的;作为限定名称,它们不受ADL约束,但在实例化过程中仍会查找它们——这允许从依赖的基中找到结果。(你的例子有一个非依赖的基础,但那也是可用的。)
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 如何在C++中从两个单独的for循环中添加两个数组
- POCO::PostgreSQL:如何将std::vector支持添加到`Binder::bind`
- 为什么在运行时没有向我们提供有关分段错误的更多信息?
- 当我们从/tp地址中添加/减去一个整数时会发生什么
- 为什么我们需要在优先级队列声明中添加一个向量作为参数?
- 模板库中的名称查找:为什么我们要添加这个>
- 为什么我们在这里将 0 添加到双空指针上?
- lambda表达式在while()中调用,为什么我们需要在lambda表达后添加()
- 我们如何添加Coverity工具的自定义规则
- 我们可以在 c++ 中使用运算符重载添加 "User defined Datatype" + "Predefined Data Type"
- C++:如果我们在字符串中添加一些整数,为什么它会从开头删除该数量的字符?(字符串 + 整数)
- 我们如何在 C++ 中使用 while 循环添加前 10 个整数
- 为什么我们在以下代码中添加偏移量以生成 3D 打印机的 GCODE
- 为什么我们不能重载构造函数来向其添加默认参数
- 我们是否需要添加调试/发布文件夹中的文件来在Visual Studio中创建安装程序
- 我们可以添加一个基于模板参数的朋友类吗
- 最大指针变量中我们可以添加多少颗星
- 当我们添加了新规则"think",如何使 udev deamon ?
- 我们可以向整数中添加一个数组变量吗?