3

私はやってみたいです:

template <class Derived=BattleData>
class BattleData : public BattleCommandManager<Derived> {
};

しかし、明らかにBattleData宣言されていないので、前方宣言を試みました:

template <class T> class BattleData;

template <class Derived=BattleData>
class BattleData : public BattleCommandManager<Derived> {
};

しかし、私は得る

エラー: 「BattleData の 2 行目のテンプレート パラメーターの番号が間違っています。

私は本当にこれに対する解決策を見ることができません!

編集

私がこれを行っている理由は、BattleDataとして直接使用できるようにしたいclassからですが、それをサブクラス化できるようにしたいためです。その場合、派生classを 2 番目のtemplateパラメーターとして指定する必要があります。

たとえば、私のBattleDataクラスのコーパスが次のようになっているとしましょう:

template <class Derived> class BattleData: public BaseClass<Derived> {
    void foo1(){};
    void foo2(){};
    void foo3(){};
}

そして、私はサブクラスを持っています

template class SubBattleData: public BattleData<SubBattleData> {
    void foo1(){};
}

場合によっては、次のようなコードを記述できるようにしたいと思います。

BattleData *x = new BattleData(...);

デフォルトの引数を使用できなければ、次のことさえできません。

BattleData<BattleData> *x = new BattleData<BattleData>(...);

一方では、関数が BattleData クラスで仮想化されていない理由は、仮想関数がないことの利点です。私にとってうまくいかないもう1つの理由は、親CRTPクラスの1つが派生型に存在する場合にのみ関数を呼び出し(decltype(Derived::function)構造体を使用してenable-ifのように)、それ以外の場合はデフォルトの動作にフォールバックすることです。特定の設計パターンを持つこれらの関数が大量に存在する可能性があるため (多くの異なるケースを持つプロトコルを読み取り、派生クラスが対応する関数を指定する場合にのみ特定の方法でケースを処理する CRTP のように、それ以外の場合は処理せずに転送するだけです) )。

したがって、これらの関数は に存在しても存在しなくてもかまいSubBattleDataませんBattleDataが、両方のクラスはインスタンス化されていれば問題なく動作しますが、インスタンス化することは不可能BattleDataです。

4

4 に答える 4

2

上記よりも自然に、元の設計目標を達成できるはずです。実際に記述しようとしているのは次のとおりであるため、実際の派生型名をデフォルトとして明確に使用することはできません。

template <class Derived=BattleData <BattleData <BattleData <...>>>
class BattleData : public BattleCommandManager<Derived> {
};

あなたはアイデアを得る。代わりに、void のようなプレースホルダーを使用してください。

template <typename T = void>
class BattleData : public BattleCommandManager <
    typename std::conditional <
        std::is_same <T, void>::value, 
        BattleData <void>,
        T
    >::type>
{
};

免責事項:私は上記をコンパイルしませんでした。

于 2012-12-24T23:18:50.453 に答える
1

あなたが何をしようとしているのかわかりません。何が問題なの

template <class T=DataContainer>
class BattleData : public BattleCommandManager< BattleData<T> > {
};

Derived実際の派生クラス以外のものを指定すると、静的ポリモーフィズムは機能せず、とにかく CRTP がいくらか役に立たなくなります。

編集:私が集めたものから、これは抽象的な言葉であなたが望むものです:

template <class Derived> 
struct Base {
    void interface() {
        static_cast<Derived*>(this)->implementation();
    }
};

template<typename T>
struct Derived : Base<Derived> {
  // dummy so we get you example
  T t;
  void implementation() {
    std::cout << "derived" << std::endl;
  }
};

struct Derived2 : public Derived<int> {
  // hide implementation in Derived
  // but still have Base::interface make the right call statically
  void implementation() {
    std::cout << "derived2" << std::endl;
  }
};

あなたがこの仕事をすることができることを私が知る方法はありません。もう 1 つのアプローチは、CRTP の代わりにポリシー クラスを使用することです。それらは継承と互換性があり、同様の動作を実現できます。

template<typename Policy>
struct BattleCmdManager : public Policy {
  using Policy::foo;
};

template<typename T>
struct BattleData {
  // ...
protected:
  void foo();
};

struct BattleData2 : public BattleData<int {
  // ...
protected:
  void foo();
};
于 2011-09-21T14:19:32.120 に答える
1

2 番目のテンプレート パラメーターに Empty クラスを使用できませんか?

template <class T=DataContainer, class Derived=BattleData<T, Empty> >
class BattleData : public BattleCommandManager<Derived> {
};
于 2011-09-21T14:59:01.207 に答える
0

これが私がそれを解決した方法です:

template <class Derived> class BattleDataInh: public BaseClass<Derived> {
    void foo1(){};
    void foo2(){};
    void foo3(){};
};

template class SubBattleData: public BattleDataInh<SubBattleData> {
    void foo1(){};
};

class BattleData : public BattleDataInh<BattleData> {
};

そうすれば、他のテンプレートパラメータも追加できます。解決策はずっと私の目の前にありましたが、私はそれを見ませんでした...

于 2011-09-22T11:19:58.883 に答える