2016-07-18 23 views
0

の転送、私はこのクラスがあります:ModuleConditionServiceのコンストラクタでC++ 11の仮想テンプレートメソッドまたは可変長引数テンプレート

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

私はこのような条件を作成します。

AddCondition(new cndActualTripID()); 

は次にメインに、私はEvaluateConditionを呼び出します。

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

すべて機能は正常ですが、機能はです3210はかなり良いとは思いません。今度はただ一つの条件cndActualTripIDがありますが、条件が100になると、そのタイプのキャスト(static_cast<cndActualTripID>(cnd))->CallOperator(operatorID, std::forward<Args>(args)...);は非常に混乱し、.hファイルの型キャストは良くないと思います。機能CallOperatorvirtualようIConditionBaseになりますときには、役立つだろうが、それはテンプレート関数である:(私はOperatorsMapSearchAndCallEvaluateConditionの引数からargsを取得する必要がありますが、私はあなたが私を助けたり、いくつかを持つことができますかわかりません他のアイデア、クラスcndActualTripID(と他の)IDIDはすべてConditionBaseを持つ継承属性です)に基づいて呼び出す方法。私はC++ 11で働いています。何を投稿すればいいですか?

ありがとうたくさんありがとう

+4

なものが存在しない可能性があるため、当然のようにそこここには、 "仮想テンプレート方法は" ありません、と。 '.hファイルの型キャストは良いとは思いません。' What?なぜそう思うの?これまでにCRTPを使用したことのある人にそのことを伝えてください。インラインメソッドでのキャストは、同じファイル内であろうとなかろうと、アウトオブラインでのキャストよりも有効ではありません。たぶんあなたは質問をもっと細かくして、それを集中させることができます。 –

+0

危険なことをしようとしています。 EvaluateConditionは1ですが、SearchAndCallは非常に悪いです。どんな型の安全性もありません。デザインの再考を検討してください。 –

+0

あなたの直ぐ質問では、SearchAndCallを捨てて、検索だけを含めることができます。マップユーザーに呼び出しをさせてください。検索はテンプレートである必要はありません。さらに、マップそのものはテンプレートである必要はありません。メンバ関数への汎用ポインタを格納するだけです。とにかくあなたの実際のタイプにキャストします(危険で、あなたが私に尋ねるならばお勧めしません)。 –

答えて

0

私のプログラムをn.mと書き直す。可変引数はありませんが、固定(ベクトル)は1つのみです。今、私は、私がストアして関数を呼び出すConditionBaseOperatorsクラスを持っています。それは以前よりも(より安全に)良いですか?おかげさまで

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); 
} 
関連する問題