尝试通过使用带有虚拟参数的模板别名隐藏基类来混淆clang和gcc时,行为上的差异

问题描述

请考虑以下c ++程序:

class A
{
    protected:
        int x;
};

template<typename X>
using B = A;

template<typename T>
class C : public B<T>
{
    public:
        void f()
        {
            x = 0;
        }
};

int main()
{
}

在使用-std=c++17 -pedantic-errors作为编译选项的clang和gcc进行编译时,它们的行为有所不同:Clang编译没有任何错误,但gcc给出了有关无法查找标识符x的编译错误。

在这种情况下,c ++标准怎么说?是否允许两种行为,或者其中一种编译器在这种情况下有错误?

编译器资源管理器链接:https://godbolt.org/z/EYvYrr

解决方法

这看起来与CWG1390类似,并且看起来Clang的行为与CWG关于如何处理此类别名模板的协议一致(在模板定义时急切替换):

1390。别名模板专业化的依赖性

根据17.7.2.1 [temp.dep.type]第8段,类型(除其他外)是从属的,

  • 一个 simple-template-id ,其中模板名称是模板参数,或者任何模板参数是从属类型或与类型或值相关的表达式

这适用于别名模板专业化,即使结果类型不取决于模板参数:

   struct B { typedef int type; };
   template<typename> using foo = B;
   template<typename T> void f() {
     foo<T>::type * x;  //error: typename required
   }

是否有必要更改此类案件的规则?

2012年10月会议的笔记:

CWG同意在这种情况下不需要typename。在某些方面,别名模板特化类似于当前实例化,并且可以在模板定义时就知道。

,

对于C ++ 17,此处的GCC是正确的。

9类型是否依赖

  • 模板参数

  • [...]

  • 一个 simple-template-id ,其中模板名称是模板参数,或者任何模板参数是从属 类型或表达式,它取决于类型或值,或者 包扩展[注:这包括一个注入的类名 没有template-argument-list的类模板。 — [请注意], 或

B<T>是一个简单模板ID,其参数是从属类型,因此B<T>表示的类型是从属类型。使用从属类型作为基类时,任何继承的成员必须通过其基类名称完全限定,或通过this->访问。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...