使用声明引入的类型与同名类型别名是否会引发声明冲突?
类型别名与基类引入的同名成员类型是否会引发声明冲突?
当类型别名的名称和通过using声明从基类引入的成员类型重名时,会不会触发声明冲突?我觉得下面这段代码应该报错,但Clang编译器却能正常编译:
template<typename> struct b {}; template<typename T> struct d : b<T> { // using b<T>::t; // 所有编译器都报错 using typename b<T>::t; // 只有Clang能编译过 using t = d; };
答案核心和C++模板的依赖名称处理规则有关:
- 代码里的
using typename b<T>::t中,t是依赖模板参数T的名称,在模板未实例化时,编译器根本无法确定b<T>里是否存在t类型,也不知道它具体是什么。 - Clang在模板定义阶段,会把这个依赖的
using声明当成“占位符”,不会立刻和后续的using t = d做冲突检查——毕竟此时还不确定前一个声明是否真的会引入名为t的实体。 - 但GCC、MSVC这类编译器在模板定义阶段就会严格检查作用域内的名称,认为同一个类作用域里不能有两个同名的类型声明,哪怕其中一个是未确定的依赖名称,因此直接报错。
另外要注意:如果模板被实例化,且基类b<T>中确实存在t类型,那么所有编译器都会报错——此时依赖的t已被解析,两个同名类型声明在同一作用域中必然冲突。只有当b<T>里完全不存在t时,Clang才会允许代码通过,因为前一个using声明相当于没有引入任何名称,后续的using t = d就是唯一有效的声明。
内容的提问来源于stack exchange,提问作者303
相关产品推荐
相关产品推荐

