I have a template child class (the template typename is not related to parent or child, so not a CRTP inheritance case), and the parent has a forward-declared class in the private access label section.
GCC (tested on 4.9.2 and 7.2) compiles, but clang (tested on 5.0.0) will complain. This is the repro case:
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 throws an error:
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
GCC however accepts this.
Now if I remove the template declaration, and make ThingImpl a non-template class, GCC will also have the same complaint about Thing being private.
Can someone explain why this is the case, and which one complies more with the C++ standard? Or does the standard not cover this explicitly?
ThingImpl<U>::handleThing()is actually instantiated, but g++ will accept it even if it is instantiated. So to be accurate, your example needs to include code that will cause the member function instantiation. - ascheplerThingImpl<TestClass> implementation;causes the instantiation of the class and its implicitly defined default constructor and destructor, but does not cause the instantiation ofThingImpl<TestClass>::handleThing(). clang++ still accepts the posted code. - aschepler