简体   繁体   English

如何使用CLASSNAME自动化模板类型名规范 <typename> (参数);

[英]how to automate template typename specification with CLASSNAME<typename>(argument);

I'm creating a stat editor for some objects within a game world. 我正在为游戏世界中的某些对象创建统计编辑器。 Rather than have multiple edit menus for each object type, I just have one menu, and pass in a list/vector of stat-edit-objects which contain a pointer to the stat being edited, and the functions to do the work. 我没有一个针对每种对象类型的多个编辑菜单,而是只有一个菜单,并传入stat-edit-objects的列表/向量,其中包含指向要编辑的stat的指针以及完成工作的功能。

struct StatEditObjPureBase
{
    std::vector<std::string> reps;
    std::string name;
    std::basic_string<int> value;
    const iWindow* win;
    Editor* pE;

    StatEditObjPureBase(iWindow& rIW, Editor& rE) : win(&rIW), pE(&rE) {}

    virtual ~StatEditObjPureBase() = 0;
    virtual StatEditObjPureBase* clone() = 0;
    virtual void set() = 0;
    virtual void dec() = 0;
    virtual void inc() = 0;
    virtual void update() = 0;
};

struct StatEditObjWrap
{
    StatEditObjPureBase* base;

    StatEditObjWrap(StatEditObjPureBase* p) : base(p) {}
    StatEditObjWrap(const StatEditObjWrap& that) { base = that.base->clone(); }
    ~StatEditObjWrap() { delete base; }
};

template<class T> struct StatEditObj_INT : StatEditObjPureBase
{
    T* pMain;

    StatEditObj_INT(T* p, iWindow& rIW, Editor& rE) : StatEditObjPureBase(rIW, rE), pMain(p) {}
    StatEditObj_INT* clone() { return new StatEditObj_INT(*this); }
    void set();
    void dec(){--(*pMain);}
    void inc(){++(*pMain);}
    void update();
};

template<class T> void StatEditObj_INT<T>::set()
{
    *pMain = input_getInt(win->box_input_y, win->box_input_x, win->box_input_range, win->box_input_fg, win->box_input_bg);
}

template<class T> void StatEditObj_INT<T>::update()
{
    staticStatEditObj_intUpdate(*pMain, value, reps);
}

My main issue is having to indicate the type of the variable whose pointer is being stored in the template derived class. 我的主要问题是必须指出变量的类型,其指针存储在模板派生类中。 The following code is a small example, but you can assume that there will be hundreds of these stat edit object entries: 以下代码是一个小示例,但是您可以假定将有数百个这些stat编辑对象条目:

void Editor::statEditObjectTemplate(ObjectTemplate& r)
{
    std::vector<iWindowEntry> temp;
    iWindow iw(17, 60, temp);

    std::vector<StatEditObjWrap> stats;

    { StatEditObjWrap stat(new StatEditObj_INT<unsigned short>(&r.glyph, iw, *this)); stats.push_back(stat); }
    { StatEditObjWrap stat(new StatEditObj_INT<unsigned int>(&r.mappedFcolour, iw, *this)); stats.push_back(stat); }
    { StatEditObjWrap stat(new StatEditObj_INT<unsigned int>(&r.mappedBcolour, iw, *this)); stats.push_back(stat); }

    statEditor(stats, iw);
}

Is there a way to have the template typename for 有没有一种方法可以为

new StatEditObj_INT<type>(&r.variable, iw, *this)

passed automatically? 自动通过?

(Note: type is for the first argument of StatEditObj_INT's constructor) (注意:类型是StatEditObj_INT的构造函数的第一个参数)

Yes, you can use a factory function: 是的,您可以使用工厂功能:

// Note:  Callee takes ownership of returned pointer
// (Alternatively, you should consider using a smart pointer like shared_ptr)
template <typename T>
StatEditObj_INT<T>* MakeNew_StatEditObj_INT(T* p, iWindow& rIW, Editor& rE)
{
    return new StatEditObj_INT<T>(p, rIW, rE);
}

Then you have: 然后您有:

stats.push_back(MakeNew_StatEditObj_INT(&r.glyph, iw, *this));
stats.push_back(MakeNew_StatEditObj_INT(&r.mappedFcolour, iw, *this));
stats.push_back(MakeNew_StatEditObj_INT(&r.mappedBcolour, iw, *this));

This works because when you use a function template, the compiler can deduce the template arguments from the function arguments (there are obviously cases where it can't, like if you have a template parameter that isn't represented in the function parameter list or is only represented in a non-deduced context). 之所以可行,是因为当您使用函数模板时,编译器可以从函数参数中推断出模板参数(显然,有些情况下不能这样做,例如您的模板参数未在函数参数列表中表示,或者仅在非推论上下文中表示)。 This is a common idiom when dealing with class templates. 在处理类模板时,这是一个常见的习惯用法。

Use a template member function in a non-template class. 在非模板类中使用模板成员函数。

struct StatEditObjWrap
{
  template <typename T>
  static StatEditObjWrap create(T* p, iWindow& rIW, Editor& rE);

  //...
}

template <typename T>
StatEditObjWrap StatEditObjWrap::create<T>(T* p, iWindow& rIW, Editor& rE) {
  return StatEditObjWrap( new StatEditObj_INT<T>( p, rIW, rE ) );
}

{
  vector<StatEditObjWrap> stats;
  stats.push_back(StatEditObjWrap::create(&r.glyph, iW, *this));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM