I'm writing a program in C++ that uses a C library. This library takes pointers to functions for callbacks, and I want it to call instance methods. Fortunately, the library takes an extra data parameter that's just a "void *" and is passed unchanged to the callback. So, I created a generic callback wrapper function.
void callbackWrapper(std::function<void ()> &func) { func();}
Now, when I need to register a callback in the library, I pass a pointer to the callbackWrapper function as the function to call, and a pointer to a std::function as the extra data parameter. When the callback happens, it calls my wrapper, which then calls the actual method/lambda/whatever I really wanted to call.
But, there's a bug in the above code. I used "&" rather than "*", which means the function is expecting a reference to a std::function, not a pointer. The function should have been defined like so:
void callbackWrapper(std::function<void ()> *func) { (*func)();}
I didn't notice the bug for quite a while -- because it worked perfectly. I only noticed because I was tracking down an unrelated bug, and just happened to see it. So, my question is, why? I have three possible answers:
- The C++ standard allows for automatic promotion of pointers to references in this circumstance.
- My compiler (gcc 9.3.1) noticed the mismatch and silently fixed it for me.
- The address of the pointer just happened to land in the right place in the stack frame that the call could succeed.
Are any of my theories correct? If not, what happened?