2009-09-01 14 views
5

これはなぜコンパイルされないのでしょうか?私はVS 2008とGCC 4.somethingの両方を試しましたが、両方ともエラーを吐き出しました。私が "ThisFunctionDoesNotCompile()"を参照しているかどうかは関係ありません。なぜこのC++テンプレートコードはコンパイルされませんか?

「InternalType」を2番目のテンプレートパラメータとしてBaseに渡すだけで回避できますが、なぜこれがエラーとして表示されるのか不思議です。

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

これらは私が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' 

そして、これらは、GCCは私を与えるものです:

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

答えて

11

テンプレートクラスBaseは次のようにインスタンス化された時点で派生クラスの親クラス、派生クラスは完全な型ではありません。

Base<Derived<DataClass> >は、親クラスのDerived<DataClass>であるため、Derived<DataClass>をインスタンス化する前にインスタンス化する必要があります。クラスBase<Derived<DataClass> >がテンプレートから構築されると、Derived<DataClass>はあたかもフォワード宣言であるかのように振る舞います。おそらくあなたが知っているように、不完全な型のメンバーを参照することはできませんし、ネストされた型を前方宣言することもできないので、ここでは不運です。

これは、テンプレートを使用して適切に共変なclone()メソッドを実装するのが難しい理由です。 hereおよびhere(私)を参照してください。

関連する問題