I want to implement a generic function returning a default value, and then use it through a function pointer as a replacement for other functions with different prototypes.
For example:
int replacement() {
return 43;
}
int (*abstract)(int i, const char *c);
int main() {
abstract = reinterpret_cast<decltype(abstract)>(replacement);
int res = (*abstract)(55, "Test");
std::cout << "Result is " << res << std::endl;
}
This code works, and actually does what I expect, but according to the standard it's undefined behaviour. Or is it?
Can I rely on the ABI to do the right thing? The parameters are passed in registers or pushed onto the stack, then if they are not used, it shouldn't be a problem. The reinterpret_cast or other equivalent cast is used for example in GTK+ and in Vulkan to pass a generic function type as pointer and letting the developers un-cast the right function type on the other end.
Is it just working by chance, or can I rely on this behaviour?
It's working purely by chance. You can never rely on undefined behavior.
.
The compiler could see that
active == falseleads to UB and therefore optimizefoounder the assumption thatactive == truealways.(No compiler I've tried does that, but that only means they haven't bothered to add such an optimization yet.)
Here's what you should do instead: variadic templates let you define a stub for any signature you need: