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.
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. –
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. –
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). –