Ik probeer een variadic template function pointer te gebruiken. Doel hiervan is om een C++ library te wrappen waarbij er via het template callback functions gegenereerd worden die uiteindelijk member functions aanroepen op een class. Het opzoeken van 'this' is hierbij geen probleem.
De onderliggende C-library werkt met een struct met function pointers die gezet kunnen worden. Een voorbeeld:
Nu wil ik dus graag een class maken die deze callbacks implementeert. Dat gaat natuurlijk niet een op een direct goed omdat een member function een this-pointer nodig heeft en dus een andere signatuur krijgt. Het ophalen van de instantie is geen enkel probleem, maar aangezien het om nogal wat callbacks gaat (met allemaal een andere signatuur) wil ik liever niet voor elke functie zelf een wrapper schrijven. Tijd voor templates dus.
Een wrapper template voor een specifieke signatuur is zo gemaakt:
Deze werkt prima voor alle callbacks met die signatuur, maar op die manier zou ik het voor alle verschillende signatures moeten gaan implementeren. Dat moet beter kunnen. De volgende manier werkt i.i.g. niet:
Dit compileert niet omdat een variadic template altijd aan het eind moet staan. Dat kan echter niet omdat we deze nodig hebben voor de function pointer. Daarnaast - als het wel zou werken - kun je type deduction dan natuurlijk wel vergeten.
Het enige dat wel werkt is het volgende:
Dit is toch niet helemaal wat ik wil aangezien ik het gevoel heb dat het mogelijk moet zijn om het type van de callback te deducen. Ik krijg het echter totaal niet voor elkaar. Zonder struct lukt het me helemaal niet wegens het kip-ei probleem van het variadic template dat aan het einde moet maar niet kan omdat ik deze nodig heb voor de function pointer. Via het struct wordt het weer erg onduidelijk.
Is er een manier om een template zo te schrijven dat het type gewoon deduced kan worden?
De onderliggende C-library werkt met een struct met function pointers die gezet kunnen worden. Een voorbeeld:
C++:
1
2
3
4
5
| struct callbacks { int(*callback1)(const char*); int(*callback2)(float); void(*callback2)(const char*, const char*); }; |
Nu wil ik dus graag een class maken die deze callbacks implementeert. Dat gaat natuurlijk niet een op een direct goed omdat een member function een this-pointer nodig heeft en dus een andere signatuur krijgt. Het ophalen van de instantie is geen enkel probleem, maar aangezien het om nogal wat callbacks gaat (met allemaal een andere signatuur) wil ik liever niet voor elke functie zelf een wrapper schrijven. Tijd voor templates dus.
Een wrapper template voor een specifieke signatuur is zo gemaakt:
C++:
1
2
3
4
5
6
| template <int(MyClass::*CALLBACK)(const char*)> static int wrapper(const char *input) { auto *instance = getInstance(); return (instance::*callback)(input); } |
Deze werkt prima voor alle callbacks met die signatuur, maar op die manier zou ik het voor alle verschillende signatures moeten gaan implementeren. Dat moet beter kunnen. De volgende manier werkt i.i.g. niet:
C++:
1
2
3
4
5
6
| template <typename RESULT, typename ...PARAMETERS, RESULT(MyClass::*callbacks)(parameters...)> static result wrapper(PARAMETERS ...parameters) { auto *instance = getInstance(); return (instance::*CALLBACK)(std::forward<Parameters...>(parameters)...); } |
Dit compileert niet omdat een variadic template altijd aan het eind moet staan. Dat kan echter niet omdat we deze nodig hebben voor de function pointer. Daarnaast - als het wel zou werken - kun je type deduction dan natuurlijk wel vergeten.
Het enige dat wel werkt is het volgende:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
| template <class T> class Callback {}; template <class T, class ...Arguments> struct Callback<T(Arguments...)> { template<T(MyClass::*CALLBACK)(Arguments...) static wrap(Arguments... parameters) { auto *instance = getInstance(); return (instance::*CALLBACK)(std::forward<Arguments>(parameters)...); } }; |
Dit is toch niet helemaal wat ik wil aangezien ik het gevoel heb dat het mogelijk moet zijn om het type van de callback te deducen. Ik krijg het echter totaal niet voor elkaar. Zonder struct lukt het me helemaal niet wegens het kip-ei probleem van het variadic template dat aan het einde moet maar niet kan omdat ik deze nodig heb voor de function pointer. Via het struct wordt het weer erg onduidelijk.
Is er een manier om een template zo te schrijven dat het type gewoon deduced kan worden?
Ik ontken het bestaan van IE.