0

CRTPについてかなり単純な質問があると思いますが、答えが見つからないようです。おそらく、あまりにも単純なため、誰も質問しようとは思いませんでした。私はコンセプトに慣れていないので、あまり笑わないでください;)。

コードは次のとおりです (STL コンテナーに似たようなことをしようとする試みのようなものです)。

template< typename tT >
struct TBase
{
  typedef tT T;
};

template< typename tTBase >
struct TTraitsBase
{
  typedef typename tTBase::T T;
};

template< typename tTHelpee, typename tTTraits >
struct THelper
{

  typedef typename tTTraits::T T;
  typedef typename tTHelpee::T Th; /* This generates a compiler error:
                                      'T' not being a member of TDerived<tT> */
  T Foo( void )
  {
   return static_cast< tTHelpee* > ( this )->mVal;
  }
};

template< typename tT >
struct TDerived : TBase< tT > , THelper< TDerived< tT > , TTraitsBase< TBase< tT > > >
{
 using TBase< tT >::T;
  T mVal;
};

int main()
{
 TDerived< int >::T lTmp = -1;
 TDerived< int > lObj;

 lObj.mVal = -1;
 std::cout << lObj.Foo() << std::endl;

 return 0;
}

問題をコメントすると、すべてがコンパイルされますtypedef typename _THelpee::T Th;。そして、それは私を混乱させます:コンパイラが好きではない場合typedef typename _THelpee::T Th;、なぜそれは通過するのstatic_cast< _THelpee* > ( this )->mValですか? THelperインスタンス化するときにインスタンス化できないことと関係があると思いますTDerivedが、明確な理解はありません。誰か、ここで何が起こっているかについて簡単な説明や参考文献を教えてください。ありがとうございました。

編集: '_T' プレフィックスを削除しました。

4

3 に答える 3

2

クラスを暗黙的にインスタンス化しても、そのメンバー関数定義はインスタンス化されません。クラステンプレートの各メンバーは、使用された場合にのみインスタンス化されます(明示的なインスタンス化を使用しない場合)。

暗黙的にインスタンス化する最初のものはTDerived<int>、の最初の行にありmainます。これをインスタンス化するために、コンパイラーはTDerivedテンプレートを検索し、依存する基本クラスがいくつかあることを確認して、それらをインスタンス化しようとします。 TBase<int>問題なくインスタンス化します。しかし、インスタンス化しようとするTHelper< TDerived<int>, TTraitsBase< TBase<int> > >と、メンバーを取得しようとしますTDerived<int>::Tが、TDerived<int>それでも不完全なタイプです。

インスタンスTHelper< ... >化は、メンバー関数があることにも注意しますがint Foo()、その定義のセマンティクスは評価しません。

それをインスタンス化するlObj.Foo()から呼び出すときまでに、は完全な型なので、問題はありません。mainint THelper< ... >::Foo()TDerived<int>

于 2011-08-29T12:12:27.520 に答える