【发布时间】: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<cndActualTripID>(cnd))->CallOperator(operatorID, std::forward<Args>(args)...); 会非常混乱,我认为在 .h 文件中进行类型转换不是一个好主意。这会有所帮助,当函数CallOperator 将像virtual 一样在IConditionBase 中时,但它是模板函数:( 我必须从EvaluateCondition 的参数中得到args 到SearchAndCall 中的SearchAndCall OperatorsMap 但我不'不知道怎么做。请你能帮我还是有其他想法,如何根据ID为cndActualTripID(和其他)类调用CallOperator(ID是具有每个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