以下代码可在clang上编译并运行,但在gcc上失败并显示“错误:对静态数据成员'Outer :: a'的无效使用”:
#include <functional>
#include <vector>
#include <assert.h>
#include <iostream>
#include <memory>
class Outer
{
public:
bool a = false;
virtual void f() = 0;
template <typename T>
class Inner : public T
{
public:
virtual void f() override
{
a = true; // Note: accessed through inheritance, not through outer scope
}
};
};
struct Foo : Outer { };
int main()
{
Outer::Inner<Foo> f;
f.f();
}
在内部类中添加“ this-> a”使其可以在两个编译器上正常工作,但是我想知道什么是正确的行为以及标准对此有何看法。
有趣的是,上面的代码在工作中作为VS2017中较大代码库的一部分工作,但是当我在单独使用VS2017的情况下在家尝试时,它失败并显示与GCC相同的错误。
您可以尝试在此处进行编译:
答案 0 :(得分:4)
此代码格式错误,无需诊断。因此,海湾合作委员会是正确和友好的。缺少对Clang和MSVC的诊断只是编译器质量问题。
涉及的标准规则为[temp.res]/8:
可以在任何实例化之前检查模板的有效性。 [注意:知道哪些名称是类型名称,这样就可以检查每个模板的语法。 —注 ] 该程序格式不正确,无需进行诊断,如果:
[..]
- 而导致格式错误
紧随其定义后的模板的假想实例化会由于格式不依赖模板参数或[...]
在f
主体中,不合格的id表达式a
不依赖于任何模板参数,因此,应在模板定义时就解决该id表达式,而无需任何知识模板参数。至此,这个表达式是不正确的。
注意:(在类成员访问之外的)非限定id表达式仅当其命名该类或非依赖基数[temp.dep.type]/5的成员时,才应视为成员:< / p>
名称是当前实例的成员,如果它是:
- 一种无限定名称,当查找时,它指的是该类的至少一个成员,该类是当前实例或其非依赖基类。