2009-09-01 13 views
5

Czy ktoś wie, dlaczego to się nie skompiluje? Próbowałem zarówno VS 2008 i GCC 4. coś i oba wypluwają błędy. Nie ma znaczenia, czy odwołuję się do "ThisFunctionDoesNotCompile()".Dlaczego ten szablon kodu C++ nie jest kompilowany?

Mogę obejść ten problem, po prostu przekazując "InternalType" jako drugi parametr szablonu do Base, ale wciąż jestem ciekawy, dlaczego to pojawia się jako błąd.

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

Są to błędy dostaję w 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' 

A oto co GCC daje mi:

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

Odpowiedz

11

W momencie, że na matrycy klasa bazowa jest tworzony jako rodzic klasy Derived, klasa Derived nie jest typem pełnym.

Ponieważ Base<Derived<DataClass> > jest klasą nadrzędną Derived<DataClass>, należy utworzyć instancję, aby można było utworzyć instancję Derived<DataClass>. Zatem, gdy klasa Base<Derived<DataClass> > jest zbudowana z szablonu, Derived<DataClass> zachowuje się tak, jakby była deklaracją forward. I jak zapewne wiesz, nie możesz odwoływać się do członków niekompletnych typów, ani nie możesz zadeklarować typów zagnieżdżonych w przód, więc nie masz szczęścia.

Tak przy okazji, trudno jest zaimplementować odpowiednio kowariancyjną metodę clone() przy użyciu szablonów. Zobacz here i here (moje).

Powiązane problemy