2010-10-21 6 views
0

Je crée un éditeur de statistiques pour certains objets dans un monde de jeu. Plutôt que d'avoir plusieurs menus d'édition pour chaque type d'objet, j'ai juste un menu, et passe dans une liste/vecteur d'objets d'édition de stat qui contiennent un pointeur vers la statistique en cours d'édition, et les fonctions pour faire le travail.comment automatiser la spécification de nom de fichier de modèle avec CLASSNAME <typename> (argument);

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

Mon problème principal est d'avoir à indiquer le type de la variable dont le pointeur est stocké dans la classe dérivée du modèle. Le code suivant est un petit exemple, mais on peut supposer qu'il y aura des centaines de ces entrées d'objet de modifier 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); 
} 

Est-il possible d'avoir le modèle typename pour

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

passé automatiquement ?

(Note: le type est le premier argument du constructeur de StatEditObj_INT)

Répondre

2

Oui, vous pouvez utiliser une fonction d'usine:

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

Ensuite, vous avez:

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

Cela fonctionne parce que lorsque vous utilisez un modèle de fonction, le compilateur peut déduire les arguments du modèle à partir des arguments de la fonction (il y a évidemment des cas où cela ne peut pas, comme si vous aviez un template para compteur qui n'est pas représenté dans la liste des paramètres de la fonction ou est représenté uniquement dans un contexte non déduit). Ceci est un idiome commun lorsqu'il s'agit de modèles de classe.

+0

Dans l'exemple de code OP donné, ne pouvait-il omettre seulement le type et laisser le compilateur le déterminer (bien comment vous faites ici avec 'MakeNew_StatEditObj_INT' – JoshD

+0

@JoshD: Non, parce que vous devez Spécifiez le nom du type dans la nouvelle expression, le compilateur ne peut pas déduire les arguments du modèle de classe d'un appel de constructeur –

+0

Merci, je ne le savais pas. – JoshD

1

Utilisez une fonction de membre modèle dans une classe sans modèle.

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