CLANG VS GCC 模板子类在父级中使用前向声明的类



我有一个模板子类(模板类型名与父类或子类无关,因此不是 CRTP 继承情况),父类在私有访问标签部分中有一个向前声明的类。

GCC(在 4.9.2 和 7.2 上测试)编译,但 clang(在 5.0.0 上测试)会抱怨。这是重现情况:

class TestClass
{
public:
    // Forward-declare as public to make compile with clang
    // class Thing;
private:
    // GCC compiles fine with forward-declaration as private but clang gives error
    class Thing;
    friend class Thing;
    void NotifyOfThing();
};
class TestClass::Thing
{
public:
    static void NotifyOfThing() {}
};
template <typename Unrelated>
class ThingImpl final : public Unrelated
{
private:
    void handleThing()
    {
        TestClass::Thing::NotifyOfThing();
    }
};
int main() {
    ThingImpl<TestClass> implementation;
}

Clang 抛出错误:

25 : <source>:25:20: error: 'Thing' is a private member of 'TestClass'
        TestClass::Thing::NotifyOfThing();
                   ^
8 : <source>:8:11: note: declared private here
    class Thing;
          ^
1 error generated.
Compiler exited with result code 1

然而,海湾合作委员会接受这一点。

现在,如果我删除模板声明,并ThingImpl非模板类,GCC 也会对Thing私有有同样的抱怨。

有人可以解释为什么会这样,哪一个更符合C++标准吗?还是标准没有明确涵盖这一点?

gcc 在访问签入模板时有很多错误。看到这个元错误。您的情况与 41437 完全匹配:

class A { struct B { B(); }; };
template<typename T> void f() { A::B b; }
void g() { f<int>(); } // gcc says this is okay

Clang是正确的,代码显然格式不正确。 ThingTestCalss的私有类,ThingImpl不是TestClass的朋友,所以ThingImpl尝试访问TestClass::Thing应该是访问冲突。

最新更新