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。

我真的看不到解决方案!

编辑

我这样做的原因是因为我希望能够BattleData直接用作 a class,但我也希望能够对其进行子类化,在这种情况下,我必须将派生指定class为第二个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 类中没有虚拟化函数的原因是没有虚拟函数的好处。它对我不起作用的另一个原因是,只有当它们存在于派生类型中时,父 CRTP 类之一才会调用函数(使用decltype(Derived::function)和 enable-if 类似的结构),否则会回退到默认行为。由于可能存在大量具有特定设计模式的函数(例如 CRTP,它读取具有许多不同案例的协议并仅在派生类指定相应函数时以特定方式处理案例,否则只需传输它而不进行处理)。

所以这些函数可以存在也可以不存在SubBattleDataBattleData但是如果实例化,这两个类都可以正常工作,但不可能实例化BattleData

4

4 回答 4

2

您应该能够比上述更自然地完成您最初的设计目标。您不能清楚地使用实际的 Derived 类型名作为默认值,因为您真正要编写的是以下内容:

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

我不知道你可以完成这项工作。另一种方法是使用策略类而不是 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

你不能对第二个模板参数使用 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 回答