使用声明的奇怪行为

A weird behavior of using-declaration

请看下面的代码

struct A { using type = int; };
struct B : private A {};
struct C : B { using base_type = A; };

所有 gcc 6.1、clang 3.8 和 msvc 2015 update 3 都拒绝编译它,因为 AC 中不是一个可访问的名称,因为 A 是一个私有库B 个。好像gcc认为using base_type = A中的A指的是A的默认构造函数。 msvc 和 clang 好像没有。

编译错误可能是由于继承引发的名称注入(因为将using base_type = A修改为using base_type = ::A使所有编译器都可以正常工作),但我想知道这个奇怪的错误是否标准是这么说的。

更具体地说,

  1. 据我了解,与 A::type 不同,A 只是一个 class 名称(尽管 gcc 将其误解为函数名称),它被引入 C 不在 A 内,也不在 B 内。为什么这个名称被认为是 B 的私有名称?
  2. 这个编译错误应该被视为错误,还是标准规范的边缘情况?

根据unqualified name lookup的规则:

(强调我的)

For an unqualified name, that is a name that does not appear to the right of a scope resolution operator ::, name lookup examines the scopes as described below, until it finds at least one declaration of any kind, at which time the lookup stops and no further scopes are examined.

因此名称A 将首先在基础class 范围内找到,全局名称空间中的名称将不会在此处考虑。之后,进行访问权限检查,然后编译失败。

::A在全局范围内指定名称并解决了问题,使其成为qualified name lookup

将我的评论作为答案发布(看起来更像是一个答案而不是评论):

我猜这是由于 Ainside C 的名称查找是如何工作的。首先,它会在使用前检查在 C 的范围内是否有任何名称为 A 的声明。由于它没有找到,它正在 B 的范围内检查它,因为它是基础 class。而万一它没有在Bs范围内找到A,它会在global namespace中查找。但不知何故,BA 的私有继承在第二次查找时停止,即在 B 的范围内。由于它使用 fully qualified 名称工作,这让我认为真正的问题必须在同一行上。