2009-09-01 10 views
5

Est-ce que quelqu'un sait pourquoi cela ne compilera pas? J'ai essayé à la fois VS 2008 et GCC 4.quelque chose et les deux cracher des erreurs. Peu importe que je fasse référence à "ThisFunctionDoesNotCompile()".Pourquoi ce code de template C++ n'est-il pas compilé?

Je peux contourner ce problème en passant simplement 'InternalType' en tant que deuxième paramètre de modèle à Base, mais je suis toujours curieux de savoir pourquoi cela se présente comme une erreur.

#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; 
} 

Ce sont les erreurs que je reçois dans 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' 

Et ce sont ce que GCC me donne:

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

Répondre

11

Au moment où la base de classe basé sur un modèle est instancié comme un parent de la classe Derived, la classe Derived n'est pas un type complet. Comme Base<Derived<DataClass> > est une classe parente de Derived<DataClass>, elle doit être instanciée avant que Derived<DataClass> puisse être instancié. Ainsi, lorsque la classe Base<Derived<DataClass> > est construite à partir du modèle, Derived<DataClass> se comporte comme s'il s'agissait d'une déclaration directe. Et comme vous le savez probablement, vous ne pouvez pas référencer les membres de types incomplets, ni vos types imbriqués de déclaration directe, donc vous n'avez pas de chance ici. C'est d'ailleurs pourquoi il est difficile d'implémenter une méthode clone() correctement covariante utilisant des templates. Voir here et here (mine).

Questions connexes