This question is for testing purposes, nothing more.
I'm currently trying to store function pointers with a different number of parameters (and these parameters can have different types).
Basically, I encoded the following code snippet in C ++ 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 will convert the function pointer void(*)(int, char, int, int) to a generic function pointer void(*)() . Then, using the template's variable parameters, I simply rewrite the pointer to its original type and call the function with some parameters.
This code compiles and runs. In most cases, it displays good values. However, this code gives me some Valgrind errors on Mac OS (regarding uninitialized values), and sometimes it displays some unexpected garbage.
==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)
I find this quite interesting because when I call the function, I reworked a pointer to its original type. I thought it looked like the lithium type was void* and then converted it to the original data type.
What is wrong with my code? Can we point to pointers to a pointer to void(*)() , and then rewrite this pointer to the original signature of the function pointer?
If not, are there other ways to achieve this? I am not interested in std::bind , which is not what I want.