考虑以下代码:
struct base {};
struct derived : public base {
using base::base;
base foo() const; // how does name lookup on 'base' here work?
};
直观地说,很明显这段代码是有效的,并且可以编译(用 gcc 和 clang 测试)。
但是,我想了解标准中的哪些内容使其有效。具体来说,我想了解名称查找base
in如何base foo()
找到基类类型而不是继承的构造函数。
这是我对标准措辞的分析,表明它应该解析为构造函数。这可能是错误的,但我想了解我哪里出错了。
我从[class.member.lookup] p1
:
成员名称查找确定类范围内名称 ( id-expression ) 的含义。[...] 对于id-expression,名称查找从类范围开始
this
p7
告诉我们名称查找的结果是什么:
[a member name]
f
在 [a class scope]中的名称查找结果是S(f, C)C
的声明集
我正在尝试使用C
beingderived
和f
正在使用base
in来遵循此过程base foo()
。
“声明集”定义在p3
:
in的查找集,称为S(f, C),由两个组件集组成:声明集,一组名为 的成员;[...]
f
C
f
p4
告诉我们声明集中的内容:
如果
C
包含 namef
的声明,则声明集包含 declare in 的每个声明f
,C
满足查找发生的语言构造的要求。
using base::base
是 ( ) 中名称( base
)f
的声明。该段继续举例说明声明不满足发生查找的语言构造的要求意味着什么,但没有任何内容可以排除在此查找之外。derived
C
using base::base
接下来,p3
我们被告知如何处理声明集中的using-declarations :
在声明集中,使用声明被派生类的成员不隐藏或覆盖的指定成员集替换
那么using base::base
指定哪些成员呢?在我看来,这是由以下人员回答的[class.qual] p2
:
在不忽略函数名称并且 嵌套名称说明符指定一个类的查找中
C
:
如果在nested-name-specifier之后指定的名称,当在 中查找时
C
,是 的注入类名C
,或者在作为成员声明的using-declaration中,如果在嵌套名称说明符之后指定的名称与嵌套名称说明符的最后一个组件中的标识符[...]相同
该名称被认为是命名 class 的构造函数
C
。
有一个脚注阐明了“不忽略函数名称的查找”的含义:
忽略函数名称的查找包括出现在嵌套名称说明符、详细类型说明符或基本说明符中的名称。
这些都不是所讨论的名称查找的情况,所以在我看来,这一段适用,并说using base::base
指定了构造函数(这也是你直观地期望的,因为它是继承构造函数声明)。
在派生类范围内找到声明(指定基类构造函数)后,我们继续以下操作[class.member.lookup] p4
:
如果结果声明集不为空,则子对象集包含
C
自身,计算完成。
也就是说,由于名称查找在派生类范围内找到了结果,因此它不会继续在基类范围内查找(它会在其中找到注入的类名称 base
)。[顺便说一句,即使名称查找继续进入基类范围,我也看不到任何可以在构造函数和注入的类名称之间消除歧义的东西]。
我的推理哪里出错了?