Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xcode/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 当使用带有多个模板参数的CRTP时,如何声明模板默认值?_C++_Templates_C++11_Crtp - Fatal编程技术网

C++ 当使用带有多个模板参数的CRTP时,如何声明模板默认值?

C++ 当使用带有多个模板参数的CRTP时,如何声明模板默认值?,c++,templates,c++11,crtp,C++,Templates,C++11,Crtp,我想做: template <class Derived=BattleData> class BattleData : public BattleCommandManager<Derived> { }; 但是我得到了 错误:“第二行的模板参数编号错误,带有 作战数据 我真的看不到解决这个问题的办法 编辑: 我这样做的原因是因为我希望能够直接使用BattleData作为类,但我也希望能够将其子类化,在这种情况下,我必须将派生的类指定为第二个模板参数 例如,假设我的Batt

我想做:

template <class Derived=BattleData>
class BattleData : public BattleCommandManager<Derived> {
};
但是我得到了

错误:“第二行的模板参数编号错误,带有 作战数据

我真的看不到解决这个问题的办法

编辑

我这样做的原因是因为我希望能够直接使用
BattleData
作为
,但我也希望能够将其子类化,在这种情况下,我必须将派生的
指定为第二个
模板
参数

例如,假设我的
BattleData
类的语料库是:

template <class Derived> class BattleData: public BaseClass<Derived> {
    void foo1(){};
    void foo2(){};
    void foo3(){};
}
如果不能使用默认参数,我甚至无法执行以下操作:

BattleData<BattleData> *x = new BattleData<BattleData>(...);
BattleData*x=新的作战数据(…);
一方面,在BattleData类中没有虚拟化函数的原因是没有虚拟函数的好处。另一个对我不起作用的原因是,父CRTP类中的一个只有在派生类型中存在函数时才会调用函数(使用
decltype(派生::函数)
并启用if-like结构),否则返回默认行为。因为可能存在大量具有特定设计模式的函数(如CRTP,它读取具有许多不同案例的协议,并且仅当派生类指定相应函数时才以特定方式处理案例,否则只需在不处理的情况下传输它)


因此,这些函数可以出现在
SubBattleData
中,而不是
BattleData
,但是如果实例化,这两个类都可以正常工作,但是实例化
BattleData
是不可能的。我看不出您想做什么。这两个类有什么问题吗

template <class T=DataContainer>
class BattleData : public BattleCommandManager< BattleData<T> > {
};
我不知道你能做到这一点。另一个 方法是使用策略类而不是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();
};
模板
结构管理器:公共策略{
使用Policy::foo;
};
模板
结构作战数据{
// ...
受保护的:
void foo();
};

struct BattleData2:public BattleData第二个模板参数不能使用空类吗

template <class T=DataContainer, class Derived=BattleData<T, Empty> >
class BattleData : public BattleCommandManager<Derived> {
};
模板
类BattleData:公共BattleCommandManager{
};

以下是我解决问题的方法:

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> {
};
模板类BattleDataInh:公共基类{
void foo1(){};
void foo2(){};
void foo3(){};
};
模板类SubBattleData:public BattleDataInh{
void foo1(){};
};
类别BattleData:公共BattleDataInh{
};

这样,我也可以添加任何其他模板参数。解决方案一直在我眼前,但我没有看到它…

你应该能够比上面更自然地完成你的原始设计目标。你不能清楚地使用实际派生的typename作为默认值,因为你真正想写的是以下:

template <class Derived=BattleData <BattleData <BattleData <...>>>
class BattleData : public BattleCommandManager<Derived> {
};
模板::类型>
{
};

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

只有当他想使用默认类型时,这才是等效的。但是如果他想提供第二个模板参数呢?@Nawaz这是我答案的一部分:你不能调用它(或者至少使用它)作为CRTP,如果他提供了与实际派生类不同的第二个模板参数。所有涉及的类都在继承链中。但从您的示例中,我看到了Policy的用法(我也在使用它来指定一些事情的行为),我只是从未想过将其用作“实现”类。我会试试看,确保它能用。试过之后,我发现了几个问题。首先,我必须使用typedef基类数据。如果BattleDataImpl需要一个额外的模板参数,这将不起作用,因为模板别名尚未实现。其次,CRTP调用主要来自其他策略,因此由于它们都是
BaseClass
的父类,因此我必须使用
dynamic\u cast(this)
而不是
static\u cast
。模板别名问题很容易解决。在上面寻找合适的问题。我不理解您的第二个问题,因为我不明白在使用策略时如何需要强制转换。抱歉。子类化:你是指虚拟函数还是静态多态性?我试着自己弄明白你想要做什么,并且做对了。看看我的建议。这是行不通的,因为当时还不知道战斗数据。谢谢!非常感谢你!以这种方式欺骗编译器是非常复杂的,我不必更改任何剩余的代码…:)@pmr,正向声明
模板类数据解决了您提到的问题,实际上,从头开始。代码编译得很好,但是当我实例化它时,我确实得到了一个无效的静态抛出错误。这是因为CRTP试图将
this
转换为
BattleData
,而派生类实际上是
BattleData
。是的,这确实有效。您甚至可以在
BattleData
中省略
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();
};
template <class T=DataContainer, class Derived=BattleData<T, Empty> >
class BattleData : public BattleCommandManager<Derived> {
};
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> {
};
template <class Derived=BattleData <BattleData <BattleData <...>>>
class BattleData : public BattleCommandManager<Derived> {
};
template <typename T = void>
class BattleData : public BattleCommandManager <
    typename std::conditional <
        std::is_same <T, void>::value, 
        BattleData <void>,
        T
    >::type>
{
};