как автоматизировать спецификацию типового имени шаблона с CLASSNAME <typename>(аргумент); - PullRequest
0 голосов
/ 22 октября 2010

Я создаю редактор статистики для некоторых объектов в игровом мире. Вместо того, чтобы иметь несколько меню редактирования для каждого типа объекта, у меня есть только одно меню, и я передаю список / вектор объектов stat-edit-edit, которые содержат указатель на редактируемую статистику и функции для выполнения работы.

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

Моя главная проблема - указывать тип переменной, указатель которой хранится в производном от шаблона классе. Следующий код является небольшим примером, но вы можете предположить, что будут сотни таких записей объекта редактирования статистики:

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

Есть ли способ иметь типовое имя шаблона для

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

прошло автоматически?

(Примечание: тип для первого аргумента конструктора StatEditObj_INT)

Ответы [ 2 ]

2 голосов
/ 22 октября 2010

Да, вы можете использовать заводскую функцию:

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

Тогда у вас есть:

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

Это работает, потому что, когда вы используете шаблон функции, компилятор может вывести аргументы шаблона из аргументов функции (очевидно, есть случаи, когда это невозможно, например, если у вас есть параметр шаблона, который не представлен в функции список параметров или представлен только в не выводимом контексте). Это распространенная идиома при работе с шаблонами классов.

1 голос
/ 22 октября 2010

Использование функции-члена шаблона в не шаблонном классе.

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