C++多继承中不同基类同名标识符的查找合法性问询
C++多继承下的标识符查找歧义问题
问题场景
- 当类继承自两个独立基类,二者均包含
using type_alias = int;类型别名时,派生类作用域中查找type_alias应解析为int还是判定为歧义? - 若两个基类的该类型别名均继承自同一共同基类,情况又如何?
示例代码
示例1:独立基类的同名声明
enum enum_type { enumerator }; template<int> struct base { using type_alias = int; using enum enum_type; }; struct derived : base<0>, base<1> {}; derived::type_alias main() { return derived::enumerator; } derived::base<2> x; // injected-class-name
示例2:共同基类的继承声明
template<int> struct super_base_template {}; struct super_base : super_base_template<0> { using type_alias = int; enum enum_type { enumerator }; static constexpr int static_member = 2; }; template<int> struct base : super_base {}; struct derived : base<0>, base<1> {}; derived::type_alias main() { return derived::enumerator; } derived::super_base_template<derived::static_member> x;
编译器行为差异
Clang可以编译所有上述代码,而GCC仅接受标识符来自同一声明的情况(如第二个代码片段,以及第一个片段的最后一行derived::base<2> x;)。
合法性分析
根据C++标准的标识符查找规则:
- 若多个直接基类中的同名声明没有共同起源(即不是来自同一个基类的同一声明),则查找会触发歧义错误。
- 若多个基类中的同名声明最终追溯到同一个共同基类的同一声明,则查找合法,无歧义。
对应示例的具体判定:
示例1
derived::type_alias和derived::enumerator:base<0>和base<1>是模板的不同实例,二者的type_alias、enumerator是独立的声明,无共同起源,属于歧义查找,标准判定为非法。Clang此处属于非标准扩展行为。derived::base<2> x;:base是注入类名,所有实例的注入类名都指向模板base本身,属于同一来源,查找合法。
示例2
derived::type_alias、derived::enumerator、derived::static_member、derived::super_base_template:这些标识符最终都来自super_base(或其基类)的同一声明,base<0>和base<1>只是继承了该声明,无歧义,所有查找操作均合法。
合法操作总结
- 示例1中仅
derived::base<2> x;合法; - 示例2中的所有标识符查找操作均合法。
内容的提问来源于stack exchange,提问作者Artyer
相关产品推荐
相关产品推荐

