Suppose I have a function that performs some side effect and then returns an answer:
int foo()
{
perform_some_side_effect();
return 42;
}
I want to bind foo
to a function pointer, but I'm not interested in the answer, just the side effect:
void (*bar)() = foo;
However, this appears to be a type error:
error: invalid conversion from ‘int (*)()’ to ‘void (*)()’
What is the rationale behind that error? Why doesn't the type system allow me to ignore the answer?
On a side note, it works if I wrap the function pointer in a std::function
:
std::function<void()> baz = foo;
How does std::function
(apparently) manage to circumvent this restriction in the type system?
What is the rationale behind that error? Why doesn't the type system allow me to ignore the answer?
The reason is that the types are different, and the generated code at the place of call (through the function pointer) is different. Consider a calling convention where all arguments are written to the stack and space for the return value is also reserved in the stack. If the call goes through a void (*)()
then no space will be reserved in the stack for the return value, but the function (unaware of how it is being called) will still write the 42
to the location where the caller should have reserved space.
How does std::function (apparently) manage to circumvent this restriction in the type system?
It does not. It creates a function object that wraps the call to the actual function. It will contain a member like:
void operator()() const {
foo();
}
Now when the compiler processes the call to foo
it knows what it has to do to call a function that returns an int
and it will do so according to the calling convention. Because the template does not return, it will just ignore the value --that was actually returned.
std::function
need only be source compatible- that is, it can generate a new class which generates new caling code that ignores the result. The function pointer must be binary compatible and cannot do that job- void(*)()
and int(*)()
point to the exact same code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With