2016-07-18 3 views
0

Ich habe diese Klassen:C++ 11 Virtual Template-Methode oder Weiterleiten variadische Vorlage

template<class C> 
class OperatorsMap 
{ 
    typedef void (C::*voidFunctionType)(void); 
    private: 
     std::map<long, voidFunctionType> m; 
    public: 
     template<typename T> 
     void Insert(long id, T f1) 
      m.insert(std::make_pair(id,(voidFunctionType)f1)); 

     template<typename O, typename... Args> 
     bool SearchAndCall(long id, O *obj, Args&&... args) 
     { 
      auto mapIter = m.find(id); 
      if(mapIter == m.end()) return false; 
      auto mapVal = mapIter->second; 
      auto Fun = (bool(C::*)(Args ...))(mapVal); 
      return (obj->*Fun)(std::forward<Args>(args)...); 
     } 
}; 

class IConditionBase 
{ 
    public: 
     virtual ConditionInfo GetInfo() = 0; 
     virtual void ClearOperators() = 0; 
}; 

template<class C> 
class ConditionBase : public IConditionBase 
{ 
public: 
    template<typename O> 
    ConditionBase(O object){mObject = object;} 
    ~ConditionBase(){} 

    ConditionInfo GetInfo(){return mInfo;} 

    template<typename F> 
    void AddOperator(long id, const char* name, F fun) 
    { 
     mInfo.AddOperatorInfo(name, id); 
     mOperators.Insert(id, fun); 
    } 

    template<typename... Args> 
    bool CallOperator(long id, Args&&... args) 
    { 
     return mOperators.SearchAndCall(id, mObject, std::forward<Args>(args)...); 
    } 

private: 
    ConditionInfo mInfo; 
    OperatorsMap<C> mOperators; 
    C* mObject; 




class ModuleConditionService 
{ 
public: 
    ModuleConditionService(); 
    ~ModuleConditionService(); 

    template<typename... Args> 
    bool EvaluateCondition(long conditionID, long operatorID, Args&&... args) 
    { 
     bool ret = false; 
     IConditionBase* cnd = GetCondition(conditionID); 
     switch(conditionID) 
     { 
      case ID_ACTUAL_TRIP_ID: (static_cast<cndActualTripID>(cnd))->CallOperator(operatorID, std::forward<Args>(args)...); 
      default: cout << "Condition with ID " << conditionID << " not found!"; 
     } 
     return ret; 
    } 

private: 
    void AddCondition(IConditionBase* condition); 
    IConditionBase *GetCondition(long conditionID); 
    vector<IConditionBase*> mConditionContainer; 
}; 

class cndActualTripID : public ConditionBase<cndActualTripID> 
{ 
    public: 
     cndActualTripID(); 
     ~cndActualTripID(); 
     using ConditionBase<cndActualTripID>::ConditionBase; 
     bool operator_Equal(long id); 
     bool operator_Greater(long id); 
     bool operator_IN(unsigned int idsCount, long ids[]); 
}; 

Im Konstruktor von ModuleConditionService Ich schaffe Bedingung wie folgt aus:

AddCondition(new cndActualTripID()); 

Dann in Haupt ich EvaluateCondition nennen:

ModuleConditionService* service = new ModuleConditionService(); 

long arr[] = {111,122,125,0,129}; 
bool ret1 = service->EvaluateCondition(1, 10, 5, arr); 
bool ret2 = service->EvaluateCondition(1, 9, 89); 
bool ret3 = service->EvaluateCondition(1, 8, 122); 

Alles funktioniert gut, aber Funktion EvaluateCondition ist nicht ganz gut, denke ich. Jetzt gibt es nur eine Bedingung cndActualTripID, aber wenn es 100 Bedingungen gibt, wird diese Art Besetzung (static_cast<cndActualTripID>(cnd))->CallOperator(operatorID, std::forward<Args>(args)...); sehr verwirrend sein und Typ in .h-Datei eingeben ist keine gute Idee, denke ich. Es würde helfen, wenn die Funktion CallOperator in IConditionBase wie virtual sein wird, aber es ist Template-Funktion :(Ich args von Argument von EvaluateCondition in SearchAndCall in OperatorsMap bekommen müssen, aber ich weiß nicht, wie. Bitte können Sie mir helfen oder haben Sie einige andere Idee, wie CallOperator für Klasse cndActualTripID (und andere) basierend auf ID (ID ist geerbt Attribut, das jede ConditionBase hat) Ich arbeite mit C++ 11. Es ist nur wichtige Teile des Codes, wenn etwas fehlt, bitte sag was und ich poste es.

Vielen Dank.

+4

Es gibt keine "virtuelle Vorlage Methoden" hier, und das zu Recht, weil es so etwas geben kann. 'Typ Cast in .h Datei ist keine gute Idee, ich denke' Was? Warum denkst du, dass? Erzählen Sie das jedem, der jemals das CRTP benutzt hat. Casting in einer Inline-Methode ist nicht mehr oder weniger gültig als Casting in einer Out-of-Line-Definition, unabhängig davon, ob sie sich in derselben Datei befindet oder nicht. Vielleicht könntest du versuchen, die Frage weiter zu reduzieren, sie zu fokussieren, anstatt mehr hinzuzufügen. –

+0

Sie versuchen, einige gefährliche Dinge zu tun. EvaluateCondition ist eins, aber SearchAndCall ist viel schlechter. Es gibt keinerlei Art von Sicherheit. Überlege dir, dein Design zu überdenken. –

+0

Auf Ihre unmittelbare Frage können Sie SearchAndCall Graben und nur eine Suche einbeziehen. Lassen Sie den Map-Benutzer den Aufruf ausführen. Die Suche muss keine Vorlage sein. Außerdem muss die Karte selbst keine Vorlage sein. Es speichert nur generische Zeiger auf Elementfunktionen. Sie werfen sie trotzdem auf Ihren tatsächlichen Typ (gefährlich und nicht empfehlenswert, wenn Sie mich fragen). –

Antwort

0

Redesign meines Programms als write n.m. Es gibt keine variablen Argumente, sondern nur einen festen (Vektor). Jetzt habe ich Klasse ConditionBaseOperators, wo ich Funktionen speichern und aufrufen. Ist es besser (sicherer) als zuvor? Danke.

template<class C> 
     class MODULECONDITIONDOMAIN_API ConditionBaseOperators : public ConditionBase 
     { 
      typedef bool (C::*Operators)(vector<string>); 

      public: 
       template<typename O> 
       ConditionBaseOperators(O obj){mObject = obj;} 
       ~ConditionBaseOperators(){} 

       void AddOperator(long id, string name, Operators function) 
       { 
        AddOperatorInfo(id, name.data()); 
        mOperators.insert(make_pair(id, function)); 
       } 

       bool CallOperator(long id, vector<string> args) 
       { 
        bool ret = false; 
        auto it = mOperators.find(id); 

        if(it != mOperators.end()) 
        { 
         auto fun = (bool(C::*)(vector<string>))(it->second); 
         ret = (mObject->*fun)(args); 
        } 
        else 
         EERROR("Operator with ID %d not found in module %s", id, GetInfo().GetName().c_str()); 

        return ret; 
       } 

      private: 
       map<long,Operators> mOperators; 
       C* mObject; 
     }; 

class MODULECONDITIONDOMAIN_API ConditionBase : public Wertyz::DomainLayer::Core::DomainObject 
     { 
      public: 
       ConditionBase(){} 
       ~ConditionBase(){} 

       ConditionInfo GetInfo(); 
       void SetInfo(ConditionInfo info); 
       void SetInfo(long id, string name); 
       void AddOperatorInfo(long id, const char* name); 

       virtual bool CallOperator(long id, vector<string> args) = 0; 

       long VtoL(vector<string> vec, unsigned int idx); 
       unsigned long VtoUL(vector<string> vec, unsigned int idx); 
       double VtoD(vector<string> vec, unsigned int idx); 
       int VtoI(vector<string> vec, unsigned int idx); 
       long long VtoLL(vector<string> vec, unsigned int idx); 
       vector<long> VtoVL(vector<string> vec); 

      private: 
       ConditionInfo mInfo; 

     }; 


class SERVICECORE_API ModuleConditionService 
     { 
     public: 
      ModuleConditionService(); 
      ~ModuleConditionService(); 

      bool EvaluateCondition(long conditionID, long operatorID, vector<string> args); 

     private: 
      void AddCondition(ConditionBase *condition); 
      void AddAction(ActionBase* action); 

      ActionBase *GetAction(long idx); 
      ConditionBase *GetCondition(long conditionID); 

      vector<ConditionBase*> mConditionContainer; 
      vector<ActionBase*> mActionContainer; 

     }; 

class MODULECONDITIONDOMAIN_API cndActualTripID : public ConditionBaseOperators<cndActualTripID> 
      { 
       public: 
        cndActualTripID(); 
        ~cndActualTripID(); 

        using ConditionBaseOperators<cndActualTripID>::ConditionBaseOperators; 

       private: 
        bool operator_Equal(vector<string> args); 
        bool operator_Greater(vector<string> args); 
        bool operator_IN(vector<string> args); 

        long GetValue(); 
      }; 

ModuleCondition.cpp

bool ModuleConditionService::EvaluateCondition(long conditionID, long operatorID, vector<string> args) 
    { 
     return GetCondition(conditionID)->CallOperator(operatorID, args); 
    } 

cndActualTripID.cpp

cndActualTripID::cndActualTripID() : ConditionBaseOperators<cndActualTripID>::ConditionBaseOperators(this) 
{ 
    SetInfo(ID_ACTUAL_TRIP_ID, "ActualTripID"); 
    AddOperator(1, "Greater", &cndActualTripID::operator_Greater); 
    AddOperator(2, "Equal", &cndActualTripID::operator_Equal); 
    AddOperator(3, "IN", &cndActualTripID::operator_IN); 
} 
Verwandte Themen