Ich habe die letzten paar Tage damit verbracht, einen generalisierten Wrapper für Funktionszeiger in C++ zu erstellen, und es ist mir gelungen, fast jeden einzelnen Fehlerbalken zu lösen. Mein Hauptziel dabei war, ein Objekt einfach als Funktion mit einem intern gespeicherten Funktionszeiger aufrufen zu können. Wenn der Zeiger irgendwo hinzeigen würde, würde er es als normal bezeichnen, während ein Nullzeiger die Funktion einfach nicht aufrufen würde, und es würde weiterlaufen, als ob nichts passiert wäre. Ich beabsichtige, dies hauptsächlich für Rückruffunktionszwecke zu verwenden, wo es mir wahrscheinlich egal wäre, ob die Funktion aufgerufen wurde oder nicht und nur eine Aktion ausführen wollte. Es funktioniert fast perfekt mit den folgenden:Verwendung von Cs '...' Parameter Pack als C++ Template Wert?
template<typename T>
class Action;
template<typename TReturn, typename ... TArgs>
class Action<TReturn(TArgs...)> {
public:
//! Define a type for the Action object
typedef TReturn(*signature)(TArgs...);
//! Constructors
inline Action(const signature& pFunc = nullptr) : mPointer(pFunc) {}
inline Action(const Action& pCopy) : mPointer(pCopy.mPointer) {}
//! Operator Call
inline bool operator() (TReturn& pReturn, TArgs ... pArgs) const { if (!mPointer) return false; pReturn = mPointer(pArgs...); return true; }
//! Operators
inline Action& operator=(const Action& pCopy) { mPointer = pCopy.mPointer; return *this; }
inline Action& operator=(const signature& pFunc) { mPointer = pFunc; return *this; }
inline operator bool() const { return (mPointer != nullptr); }
private:
//! Store a pointer to the callback function
signature mPointer;
};
template<typename ... TArgs>
class Action<void(TArgs...)> {
public:
//! Define a type for the Action object
typedef void(*signature)(TArgs...);
//! Constructors
inline Action(const signature& pFunc = nullptr) : mPointer(pFunc) {}
inline Action(const Action& pCopy) : mPointer(pCopy.mPointer) {}
//! Operator Call
inline bool operator() (TArgs ... pArgs) const { if (!mPointer) return false; mPointer(pArgs...); return true; }
//! Operators
inline Action& operator=(const Action& pCopy) { mPointer = pCopy.mPointer; return *this; }
inline Action& operator=(const signature& pFunc) { mPointer = pFunc; return *this; }
inline operator bool() const { return (mPointer != nullptr); }
private:
//! Store a pointer to the callback function
signature mPointer;
};
Aber ich wie die Situation spüren, würde höchstwahrscheinlich Verwendung dieser Wrapper die Ausgabe von Debug-Informationen oder formatierten Text. Dies kann durch benutzerdefinierte Funktionen oder eingebaute Funktionen wie printf geschehen. Um mit printf Unterschrift übereinstimmen würde eine Aktion wie erstellt werden:
Action<int(const char*, ...)> callback = printf;
und es wäre in der Lage, die gleiche Art und Weise zu betreiben, dass jede andere Aktion verhalten würde. Das Problem, das ich finde, ist das '...' wird dazu führen, dass die Vorlagensignatur nicht mit einer der Spezialisierungen übereinstimmt, sondern mit der ersten, die nur ein Prototyp ist.
Ich kann vollständig verstehen, warum das nicht funktioniert und warum der Compiler nicht in der Lage wäre, die Generierung der erforderlichen Klasse zu bewältigen, aber ich hoffte, dass jemand hier irgendwelche hinterhältigen Wege kennen würde, um dies oder etwas ähnliches zu erreichen. Jede Hilfe wäre sehr geschätzt, Dank :)
Warum nicht 'std :: function' verwenden? – StoryTeller
Was ist der Zweck von "Aktion"? Welche Voraussetzung haben Sie, dass Sie ['std :: function'] (http://en.cppreference.com/w/cpp/utility/functional/function) nicht verwenden können? Welches Problem löst 'Action', dass' std :: function' nicht funktioniert? –
https://stackoverflow.com/questions/18370396/why-cant-stdfunction-bind-to-c-style-varijadic-functions gab einen Kommentar, wie man das fast erreichen kann. Ich denke für jede variadic Funktion, Sie würden eine konkrete Klasse benötigen, um Ihnen zu helfen, und hoffen, dass es eine v * Variante der Funktion gab, die Sie nennen konnten. – mksteve