【问题标题】:C++11 Virtual template method or Forwarding variadic templateC++11 虚拟模板方法或转发可变参数模板
【发布时间】:2016-07-18 11:19:02
【问题描述】:

我有这些课程:

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

ModuleConditionService 的构造函数中,我创建了这样的条件:

AddCondition(new cndActualTripID());

然后在 main 我调用 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);

一切正常,但我认为EvaluateCondition 功能不太好。现在只有一个条件cndActualTripID,但是当有 100 个条件时,类型转换 (static_cast&lt;cndActualTripID&gt;(cnd))-&gt;CallOperator(operatorID, std::forward&lt;Args&gt;(args)...); 会非常混乱,我认为在 .h 文件中进行类型转换不是一个好主意。这会有所帮助,当函数CallOperator 将像virtual 一样在IConditionBase 中时,但它是模板函数:( 我必须从EvaluateCondition 的参数中得到argsSearchAndCall 中的SearchAndCall OperatorsMap 但我不'不知道怎么做。请你能帮我还是有其他想法,如何根据IDcndActualTripID(和其他)类调用CallOperatorID是具有每个ConditionBase的继承属性). 我使用 c++11。它只是代码的重要部分,如果缺少某些内容,请告诉我,我将其发布。

非常感谢。

【问题讨论】:

  • 这里没有“虚拟模板方法”,这是正确的,因为不可能存在这样的东西。 type cast in .h file isn't good idea I think 什么?为什么你这么想?告诉所有曾经使用过 CRTP 的人。内联方法中的强制转换与外联定义中的强制转换一样有效,无论它是否在同一个文件中。也许你可以尝试进一步缩小问题,集中注意力,而不是增加更多。
  • 你正在尝试做一些危险的事情。 EvaluateCondition 是一个,但 SearchAndCall 更糟糕。没有任何类型安全。考虑重新考虑您的设计。
  • 在您的直接问题上,您可以放弃 SearchAndCall 并只包含一个搜索。让地图用户进行调用。搜索不必是模板。此外,地图本身不必是模板。它只存储指向成员函数的通用指针。无论如何,您将它们转换为您的实际类型(如果您问我,这很危险,不推荐)。
  • 谢谢 n.m.请问我应该如何重新设计我的应用程序。你能指导我到正确的道路吗?非常感谢。

标签: c++ templates c++11 abstract variadic-templates


【解决方案1】:

我将我的程序重新设计为 write n.m.没有可变参数,只有一个固定(向量)。现在我有了 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();
            };

模块条件.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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-28
    • 2011-12-19
    • 2021-06-16
    • 2014-10-25
    • 2015-11-10
    相关资源
    最近更新 更多