继承构造函数后查找基 class 名称
Lookup of base class name after inheriting constructor
考虑以下代码:
struct base {};
struct derived : public base {
using base::base;
base foo() const; // how does name lookup on 'base' here work?
};
直觉上,很明显这段代码是有效的,并且确实可以编译(用 gcc 和 clang 测试过)。
但是,我想了解标准中的哪些内容使其有效。具体来说,我想了解 base foo()
中 base
的名称查找如何找到基 class 类型而不是继承的构造函数。
这是我对标准措辞的分析,表明它应该解析为构造函数。这可能是错误的,但我想了解我哪里出错了。
我从 [class.member.lookup] p1
开始:
Member name lookup determines the meaning of a name (id-expression) in a class scope. [...] For an id-expression, name lookup begins in the class scope of this
p7
告诉我们名称查找的结果是什么:
The result of name lookup for [a member name] f
in [a class scope] C
is the declaration set of S(f, C)
我正在尝试遵循此过程,其中 C
是 derived
,f
是 base foo()
中 base
的使用。
"Declaration set" 定义在 p3
:
The lookup set for f
in C
, called S(f, C), consists of two component sets: the declaration set, a set of members named f
; [...]
p4
告诉我们什么进入声明集:
If C
contains a declaration of the name f
, the declaration set contains every declaration of f
declared in C
that satisfies the requirements of the language construct in which the lookup occurs.
using base::base
是derived
(C
)中名字base
(f
)的声明。该段继续举例说明声明 not 满足发生查找的语言结构的要求的含义,但没有任何内容可以排除 using base::base
从这个查找。
接下来,在 p3
中,我们被告知如何处理声明集中的 using-declarations:
In the declaration set, using-declarations are replaced by the set of designated members that are not hidden or overridden by members of the derived class
那么using base::base
指派了哪些成员呢?在我看来 [class.qual] p2
:
In a lookup in which function names are not ignored and the
nested-name-specifier nominates a class C
:
if the name specified after the nested-name-specifier, when looked up in C
, is the injected-class-name of C
, or
in a using-declaration that is a member-declaration, if the name specified after the nested-name-specifier is the same as
identifier [...] in the last component of the nested-name-specifier
the name is instead considered to name the constructor of class C
.
有一个脚注阐明了 "lookup in which function names are not ignored" 的含义:
Lookups in which function names are ignored include names appearing in a nested-name-specifier, an elaborated-type-specifier, or a base-specifier.
None 这些是有问题的名称查找的情况,所以在我看来这一段适用,并说 using base::base
指定构造函数(这也是你的d 直观地期待,因为它是继承构造函数声明)。
在派生的 class 范围内找到一个声明(指定基 class 构造函数),我们继续遵循 [class.member.lookup] p4
:
If the resulting declaration set is not empty, the subobject set contains C
itself, and calculation is complete.
也就是说,由于名称查找在派生的 class 范围内找到结果,因此它不会继续在基础 class 范围内查找(它将在其中找到 注入-class-名称 base
)。 [顺便说一句,即使名称查找继续进入基础 class 范围,我也看不到任何可以消除构造函数和 injected-class-name].
我的推理哪里出了问题?
标准煞费苦心地指出构造函数没有名称。无法通过名称查找找到它,因为它没有名称。
C++11 §12.1/1
” Constructors do not have names.
C+11 §12.1/2
” Because constructors do not have names, they are
never found during name lookup.
考虑以下代码:
struct base {};
struct derived : public base {
using base::base;
base foo() const; // how does name lookup on 'base' here work?
};
直觉上,很明显这段代码是有效的,并且确实可以编译(用 gcc 和 clang 测试过)。
但是,我想了解标准中的哪些内容使其有效。具体来说,我想了解 base foo()
中 base
的名称查找如何找到基 class 类型而不是继承的构造函数。
这是我对标准措辞的分析,表明它应该解析为构造函数。这可能是错误的,但我想了解我哪里出错了。
我从 [class.member.lookup] p1
开始:
Member name lookup determines the meaning of a name (id-expression) in a class scope. [...] For an id-expression, name lookup begins in the class scope of
this
p7
告诉我们名称查找的结果是什么:
The result of name lookup for [a member name]
f
in [a class scope]C
is the declaration set of S(f, C)
我正在尝试遵循此过程,其中 C
是 derived
,f
是 base foo()
中 base
的使用。
"Declaration set" 定义在 p3
:
The lookup set for
f
inC
, called S(f, C), consists of two component sets: the declaration set, a set of members namedf
; [...]
p4
告诉我们什么进入声明集:
If
C
contains a declaration of the namef
, the declaration set contains every declaration off
declared inC
that satisfies the requirements of the language construct in which the lookup occurs.
using base::base
是derived
(C
)中名字base
(f
)的声明。该段继续举例说明声明 not 满足发生查找的语言结构的要求的含义,但没有任何内容可以排除 using base::base
从这个查找。
接下来,在 p3
中,我们被告知如何处理声明集中的 using-declarations:
In the declaration set, using-declarations are replaced by the set of designated members that are not hidden or overridden by members of the derived class
那么using base::base
指派了哪些成员呢?在我看来 [class.qual] p2
:
In a lookup in which function names are not ignored and the nested-name-specifier nominates a class
C
:
if the name specified after the nested-name-specifier, when looked up in
C
, is the injected-class-name ofC
, orin a using-declaration that is a member-declaration, if the name specified after the nested-name-specifier is the same as identifier [...] in the last component of the nested-name-specifier
the name is instead considered to name the constructor of class
C
.
有一个脚注阐明了 "lookup in which function names are not ignored" 的含义:
Lookups in which function names are ignored include names appearing in a nested-name-specifier, an elaborated-type-specifier, or a base-specifier.
None 这些是有问题的名称查找的情况,所以在我看来这一段适用,并说 using base::base
指定构造函数(这也是你的d 直观地期待,因为它是继承构造函数声明)。
在派生的 class 范围内找到一个声明(指定基 class 构造函数),我们继续遵循 [class.member.lookup] p4
:
If the resulting declaration set is not empty, the subobject set contains
C
itself, and calculation is complete.
也就是说,由于名称查找在派生的 class 范围内找到结果,因此它不会继续在基础 class 范围内查找(它将在其中找到 注入-class-名称 base
)。 [顺便说一句,即使名称查找继续进入基础 class 范围,我也看不到任何可以消除构造函数和 injected-class-name].
我的推理哪里出了问题?
标准煞费苦心地指出构造函数没有名称。无法通过名称查找找到它,因为它没有名称。
C++11 §12.1/1C+11 §12.1/2” Constructors do not have names.
” Because constructors do not have names, they are never found during name lookup.