使用声明

时间:2016-07-04 08:13:37

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

请参阅以下代码

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的私有基础{1}}。似乎gcc认为Ausing base_type = A引用了A的默认构造函数。 msvc和clang似乎没有。

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

更具体地说,

  1. 据我了解,不像A::typeA只是一个类名(尽管gcc将其误解为函数名),它被引入C 而不是< / em> AB。为什么此名称被视为B的私人名称?
  2. 此编译错误是否应被视为错误,或者是标准规范的边缘情况?

2 个答案:

答案 0 :(得分:28)

根据unqualified name lookup的规则:

(强调我的)

  

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

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

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

答案 1 :(得分:2)

将我的评论作为答案发布(似乎答案不仅仅是评论):

我猜这是因为AC的名称查找工作原理。首先,它在使用前检查是否在A范围内查找名称为C的任何内容。由于它没有找到,因此它在B的范围内进行检查,因为它是Base类。并且以防在Bs范围内找不到A,它会在global namespace中查找。但不知何故,A B的私有继承在第二次查找时停止,即在B范围内。由于它使用fully qualified名称,这使我认为真正的问题必须在同一条线上。