9

ポリシー ベースのホスト クラス (つまり、テンプレート クラスから継承するクラス) を作成しようとしていますが、ポリシー クラスもホスト クラスによってテンプレート化されているため、その型にアクセスできます。これが役立つ 1 つの例は、ポリモーフィックな clone() メソッドでホスト クラスを拡張するポリシー (実際には mixin のように使用される) です。これが私がやろうとしていることの最小限の例です:

template <template <class> class P>
struct Host : public P<Host<P> > {
  typedef P<Host<P> > Base;
  typedef Host* HostPtr;
  Host(const Base& p) : Base(p) {}
};

template <class H>
struct Policy {
  typedef typename H::HostPtr Hptr;
  Hptr clone() const {
    return Hptr(new H((Hptr)this));
  }
};

Policy<Host<Policy> > p;
Host<Policy> h(p);

int main() {
  return 0;
}

残念ながら、これはコンパイルに失敗します。循環型依存関係のように思えます。

try.cpp: In instantiation of ‘Host<Policy>’:
try.cpp:10:   instantiated from ‘Policy<Host<Policy> >’
try.cpp:16:   instantiated from here
try.cpp:2: error: invalid use of incomplete type ‘struct Policy<Host<Policy> >’
try.cpp:9: error: declaration of ‘struct Policy<Host<Policy> >’
try.cpp: In constructor ‘Host<P>::Host(const P<Host<P> >&) [with P = Policy]’:
try.cpp:17:   instantiated from here
try.cpp:5: error: type ‘Policy<Host<Policy> >’ is not a direct base of ‘Host<Policy>’

誰かが明らかな間違いを見つけた場合、またはポリシーに CRTP をうまく混在させることができた場合は、助けていただければ幸いです。

4

1 に答える 1

7

実際、問題はHostPtr、ポリシーから継承するときに宣言がまだ表示されていないことが原因です。これらの宣言がインスタンス化されたテンプレートによって表示される正確なセマンティクスについていくつかの議論があり、これにはかなり複雑な問題があります。この欠陥レポートを参照してください。

しかし、あなたの場合、状況は明らかです。クラス本体の前では、コードはクラス メンバーの宣言を確認できないため、コードは失敗します。タイプをテンプレート引数として渡すことができます

template <template <class,class> class P>
struct Host : public P<Host<P>, Host<P>* > {
  typedef P<Host<P> > Base;
  Host(const Base& p) : Base(p) {}
};

template <class H, class Hptr>
struct Policy {
  typedef Hptr HostPtr;
  HostPtr clone() const {
    return Hptr(new H((Hptr)this));
  }
};

より多くのタイプがある場合は、特性を渡すことを決定できます

template <class Host>
struct HTraits {
  typedef Host *HostPtr;
  // ...
};

template <template <class,class> class P>
struct Host : public P<Host<P>, HTraits< Host<P> > > {
  typedef P<Host<P> > Base;
  Host(const Base& p) : Base(p) {}
};

template <class H, class Htraits>
struct Policy {
  typedef typename Htraits::HostPtr HostPtr;
  HostPtr clone() const {
    return Hptr(new H((Hptr)this));
  }
};
于 2010-04-11T13:16:39.133 に答える