继承构造函数后查找基 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)

我正在尝试遵循此过程,其中 Cderivedfbase 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::basederived(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.