Spędziłem kilka ostatnich dni próbując stworzyć uogólnione opakowanie sortowania dla wskaźników funkcji w C++ i udało mi się rozwiązać prawie każdy pasek pojedynczego problemu. Moim głównym celem było po prostu wywołanie obiektu jako funkcji ze wskaźnikiem funkcji przechowywanym wewnętrznie. Jeśli wskazówka wskazywałaby gdzieś, to nazwałaby to normalnie, podczas gdy wskaźnik zerowy nie wywoływałby tej funkcji i działałby tak, jakby nic się nie stało. Zamierzam użyć tego przede wszystkim do celów funkcji zwrotnej, gdzie prawdopodobnie nie dbałbym o to, czy funkcja została wywołana czy nie i po prostu chciałem wykonać akcję. To działa prawie idealnie z następujących czynności:Użycie zestawu parametrów C '...' jako wartości szablonu C++?
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;
};
Jednak czuję się z sytuacją, że najprawdopodobniej to wykorzystanie wrapper jest wyjście z informacji debugowania lub sformatowanego tekstu. Może to wynikać z funkcji zdefiniowanych przez użytkownika lub wbudowanych funkcji, takich jak printf. Aby dopasować podpis printf dodatkowych działań byłyby tworzone jak:
Action<int(const char*, ...)> callback = printf;
i byłoby w stanie działać w ten sam sposób, że wszelkie inne działania będą zachowywać. Problem, który znajduję, polega na tym, że "..." wymusi podpis szablonu, aby nie dopasować się do żadnej z tych specjalizacji, zamiast tego iść z pierwszym, który jest tylko prototypem.
W pełni rozumiem, dlaczego to nie działa i dlaczego kompilator nie byłby w stanie obsłużyć generowania wymaganej klasy, ale miałem nadzieję, że ktoś tutaj zna jakieś podstępne sposoby, aby to osiągnąć lub coś podobnego. Każda pomoc będzie mile widziane, thanks :)
Dlaczego nie skorzystać z 'std :: function'? – StoryTeller
Jaki jest cel "działania"? Jakie masz wymagania, że nie możesz użyć ['std :: function'] (http://en.cppreference.com/w/cpp/utility/functional/function)? Jaki problem rozwiązuje "Action", że 'std :: function' does not? –
https://strojverflow.com/questions/18370396/why-cant-stdfunction-bind-to-c-style-variadic-functions dał kilka komentarzy, jak osiągnąć prawie to. Myślę, że dla każdej funkcji variadic potrzebujesz konkretnej klasy, która Ci pomoże, i mam nadzieję, że istnieje wariant v * funkcji, którą możesz wywołać. – mksteve