Why doesn't this C++ template code compile?

c++, compiler-errors, templates

Solution

At the time that the templated class Base is instantiated as a parent of the class Derived, the class Derived is not a complete type.

Since `Base<Derived<DataClass> >` is a parent class of `Derived<DataClass>`, it must be instantiated before `Derived<DataClass>` can be instantiated. So when the class `Base<Derived<DataClass> >` is built from the template, `Derived<DataClass>` behaves as if it were a forward declaration. And as you're probably aware, you can't reference members of incomplete types, nor can your forward-declare nested types, so you're out of luck here.

This, by the way, is why it's difficult to implement a properly covariant clone() method using templates. See here and here (mine).

Problem

Does anyone know why this will not compile? I've tried both VS 2008 and GCC 4.something and both spit out errors. It doesn't matter whether or not I'm referencing "ThisFunctionDoesNotCompile()". I can workaround this by just passing 'InternalType' as a second template parameter to Base, but I'm still curious why this comes up as an error. ``` #include <iostream> using namespace std; class DataClass { public: int m_data; }; template<typename DerivedType> class Base { public: int ThisFunctionCompiles() { // No problems here. typename DerivedType::InternalType temp; temp.m_data = 5; return temp.m_data; } // error C2039: 'InternalType' : is not a member of 'Derived<InInternalType>' typename DerivedType::InternalType ThisFunctionDoesNotCompile() { return static_cast<DerivedType*>(this)->GetInternalData(); } }; template<typename InInternalType> class Derived : public Base<Derived<InInternalType> > { public: typedef InInternalType InternalType; InternalType GetInternalData() { return m_internalData; } private: InternalType m_internalData; public: void SetInternalData( int newVal ) { m_internalData.m_data = newVal; } }; int main() { Derived<DataClass> testDerived; testDerived.SetInternalData( 3 ); cout << testDerived.GetInternalData().m_data << endl; cout << testDerived.ThisFunctionCompiles() << endl; // The compiler gives an error regardless of whether or not this is commented out. //cout << testDerived.ThisFunctionDoesNotCompile().m_data << endl; return 0; } ``` These are the errors I get in VS 2008: ``` 1>e:\test\generaltestprogram\generaltestprogram\main.cpp(27) : error C2039: 'InternalType' : is not a member of 'Derived<InInternalType>' 1> with 1> [ 1> InInternalType=DataClass 1> ] 1> e:\test\generaltestprogram\generaltestprogram\main.cpp(35) : see reference to class template instantiation 'Base<DerivedType>' being compiled 1> with 1> [ 1> DerivedType=Derived<DataClass> 1> ] 1> e:\test\generaltestprogram\generaltestprogram\main.cpp(58) : see reference to class template instantiation 'Derived<InInternalType>' being compiled 1> with 1> [ 1> InInternalType=DataClass 1> ] 1>e:\test\generaltestprogram\generaltestprogram\main.cpp(27) : error C2146: syntax error : missing ';' before identifier 'ThisFunctionDoesNotCompile' 1>e:\test\generaltestprogram\generaltestprogram\main.cpp(27) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int 1>e:\test\generaltestprogram\generaltestprogram\main.cpp(28) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int 1>e:\test\generaltestprogram\generaltestprogram\main.cpp(28) : warning C4183: 'ThisFunctionDoesNotCompile': missing return type; assumed to be a member function returning 'int' ``` And these are what GCC gives me: ``` main.cpp: In instantiation of 'Base<Derived<DataClass> >': main.cpp:96: instantiated from 'Derived<DataClass>' main.cpp:119: instantiated from here main.cpp:88: error: no type named 'InternalType' in 'class Derived<DataClass>' ```

Original source