【问题标题】:A weird behavior of using-declaration使用声明的奇怪行为
【发布时间】:2016-11-05 21:27:51
【问题描述】:

请看下面的代码

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

所有 gcc 6.1、clang 3.8 和 msvc 2015 更新 3 都拒绝编译它,因为 A 不是 C 内的可访问名称,因为 AB 的私有基础。看来gcc认为using base_type = A中的A指的是A的默认构造函数。 msvc 和 clang 似乎没有。

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

更具体地说,

  1. 据我了解,不像A::typeA 只是一个类名(尽管 gcc 将其误解为函数名),它被引入到C 不在里面 A也不是B。为什么此名称被视为 B 的私有名称?
  2. 应将此编译错误视为错误,还是标准规范的边缘情况?

【问题讨论】:

  • 我猜这是因为AC 中的名称查找是如何工作的。首先,它检查是否在C 的范围内,在using 之前声明了名称为A 的任何内容。因为它没有找到一个,所以它在B 的范围内检查它,因为它是基类。如果在Bs 范围内找不到A,它会在global namespace 中查找。但不知何故,BAprivate inheritance 在第二次查找时停止,即在B 的范围内。由于它使用fully qualified 名称工作,这让我认为真正的问题必须在同一行。
  • @PiotrSkotnicki 谢谢,它直接回答了这个问题。但是,你能告诉我这条规则背后的理由吗?
  • @PiotrSkotnicki 好吧,没关系。我想我对事情有些了解。谢谢!

标签: c++ c++11 name-lookup using-declaration private-inheritance


【解决方案1】:

根据unqualified name lookup的规则:

(强调我的)

对于非限定名称,即未出现在范围解析运算符 :: 右侧的名称,名称查找会按如下所述检查范围,直到找到至少一个任何类型的声明,此时查找停止并且不再检查范围

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-25
      相关资源
      最近更新 更多