Diese Frage ist für Testzwecke, nichts mehr.Casting Funktionszeiger auf void (*)(), dann neu zu ursprünglichen Typ
Ich versuche derzeit, Funktionszeiger mit einer anderen Anzahl von Parametern zu speichern (und diese Parameter können unterschiedliche Typen haben).
Grundsätzlich habe ich das folgende Codefragment in C++ codiert 11:
#include <functional>
#include <iostream>
void fct(int nb, char c, int nb2, int nb3) {
std::cout << nb << c << nb2 << nb3 << std::endl;
}
template <typename... Args>
void call(void (*f)(), Args... args) {
(reinterpret_cast<void(*)(Args...)>(f))(args...);
}
int main(void) {
call(reinterpret_cast<void(*)()>(&fct), 42, 'c', 19, 94);
}
I wandle einen void(*)(int, char, int, int)
Funktionszeiger in ein generischen void(*)()
Funktionszeiger. Dann benutze ich variante Template-Parameter einfach den Funktionszeiger auf seinen ursprünglichen Typ um und rufe die Funktion mit einigen Parametern auf.
Dieser Code wird kompiliert und ausgeführt. Meistens zeigt es die guten Werte an. Dieser Code gibt mir unter Mac OS jedoch einige Valgrind-Fehler (in Bezug auf nicht initialisierte Werte) und zeigt manchmal unerwarteten Müll an.
==52187== Conditional jump or move depends on uninitialised value(s)
==52187== at 0x1004E4C3F: _platform_memchr$VARIANT$Haswell (in /usr/lib/system/libsystem_platform.dylib)
==52187== by 0x1002D8B96: __sfvwrite (in /usr/lib/system/libsystem_c.dylib)
==52187== by 0x1002D90AA: fwrite (in /usr/lib/system/libsystem_c.dylib)
==52187== by 0x100025D29: std::__1::__stdoutbuf<char>::overflow(int) (in /usr/lib/libc++.1.dylib)
==52187== by 0x10001B91C: std::__1::basic_streambuf<char, std::__1::char_traits<char> >::xsputn(char const*, long) (in /usr/lib/libc++.1.dylib)
==52187== by 0x10003BDB0: std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> > std::__1::__pad_and_output<char, std::__1::char_traits<char> >(std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> >, char const*, char const*, char const*, std::__1::ios_base&, char) (in /usr/lib/libc++.1.dylib)
==52187== by 0x10003B9A7: std::__1::num_put<char, std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> > >::do_put(std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> >, std::__1::ios_base&, char, long) const (in /usr/lib/libc++.1.dylib)
==52187== by 0x1000217A4: std::__1::basic_ostream<char, std::__1::char_traits<char> >::operator<<(int) (in /usr/lib/libc++.1.dylib)
==52187== by 0x1000011E8: fct(int, char, int, int) (in ./a.out)
==52187== by 0x1000013C2: void call<int, char, int, int>(void (*)(), int, char, int, int) (in ./a.out)
==52187== by 0x100001257: main (in ./a.out)
Ich finde das ziemlich merkwürdig, denn wenn ich die Funktion aufruft, habe ich den Funktionszeiger auf seinen ursprünglichen Typ umgestuft. Ich dachte, es wäre ähnlich, einen Datentyp auf void*
zu übertragen und dann in den ursprünglichen Datentyp zu reastieren.
Was ist falsch an meinem Code? Können wir nicht Funktionszeiger auf void(*)()
Zeiger werfen und dann diesen Zeiger auf die ursprüngliche Funktionszeiger-Signatur umwandeln?
Wenn nicht, gibt es andere Möglichkeiten, dies zu erreichen? Ich bin nicht interessiert an std::bind
was nicht was ich will.
Sie meinen Funktionszeiger? Nicht Zeiger auf Mitgliedsfunktionen? – MSalters
Ich kann das nicht reproduzieren. Ist das dein tatsächlicher, wörtlicher Testfall? –
Ja, das ist genau der Code, den ich ausgeführt habe (auf Macos Yosemite). Außerdem, wenn ich den letzten Parameter durch einen std :: string ersetze, habe ich Müll. –