2009-09-01 20 views
5

¿Alguien sabe por qué esto no compilará? Intenté tanto VS 2008 como GCC 4. algo y ambos escupí errores. No importa si estoy haciendo referencia o no a "ThisFunctionDoesNotCompile()".¿Por qué no se compila este código de plantilla C++?

Puedo solucionar esto simplemente pasando 'InternalType' como un segundo parámetro de plantilla a Base, pero todavía tengo curiosidad de por qué esto aparece como un 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; 
} 

Estos son los errores que recibo en 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' 

Y estos son los que GCC me da:

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>' 

Respuesta

11

En el momento en que la base de la clase de plantilla se crea una instancia como un padre de la clase Derivada, la clase derivada no es un tipo completo.

Dado que Base<Derived<DataClass> > es una clase principal de Derived<DataClass>, se debe instanciar antes de que se pueda crear una instancia de Derived<DataClass>. Por lo tanto, cuando la clase Base<Derived<DataClass> > se crea a partir de la plantilla, Derived<DataClass> se comporta como si fuera una declaración directa. Y como seguramente sabrá, no puede hacer referencia a los miembros de tipos incompletos, ni puede anunciar los tipos anidados, por lo que no tiene suerte aquí.

Esto, dicho sea de paso, es la razón por la cual es difícil implementar un método clone() covariante correctamente utilizando plantillas. Ver here y here (mío).

Cuestiones relacionadas