我想要做:

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用作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-like结构),否则返回默认行为。由于可能存在大量具有特定设计模式的功能(例如,CRTP仅在派生类指定了相应功能的情况下读取具有许多不同情况的协议(protocol)并以特殊方式处理情况,否则,无需处理即可直接将其转移)。

因此,这些函数可以出现在SubBattleData中,而不是BattleData中,但是如果实例化这两个类,它们都可以正常工作,但无法实例化BattleData

最佳答案

您应该能够比以上更自然地完成原始设计目标。您不能明确地使用实际的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>
{
};

免责声明:我没有编译以上内容。

关于c++ - 将CRTP与多个模板参数一起使用时,如何声明模板默认值?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7501235/

10-11 23:08