I am confused about using C++ function pointers.
using fn_p1 = void(int); // function pointer
using fn_p2 = void (*)(int);
void functional(fn_p1 f) {
f(1);
}
void callback(int value){
// do something
}
int main() {
fn_p2 f = callback; //works
fn_p1 f1 = static_cast<fn_p1>(f); //does not work
fn_p1 f2 = callback; //does not work
fn_p1 f2 = static_cast<fn_p1>(callback); //does not work
functional(f); // works, the argument is form of void(*)(int)
f(1); // works
functional(*f); // works, the argument is dereferenced, void(int)
(*f)(1); // works
return 0;
}
I know there is no difference if you call a function pointer with f(1), (*f)(1), or (*****f)(1).
I don't get how functional(f); works but fn_p1 f1 = static_cast<fn_p1>(f); and its variants can not since they define the function pointer as using fn_p1 = void(int);.
Could anyone explain how the function pointer works or how the compiler deals with it?
The most useful error that the IDE should give you is on the line
fn_p1 f2 = callback;:(This is the message I get from clangd.)
That means literally that an entity of type
void(int)(or more in generalsomeReturnType(someArgTypes...)) is not a variable.Indeed, in C++ functions are not first class, which means that you can't pass them to function and don't get them in return from function; when you think you are successfully doing so, you're in reality passing or taking back function pointers.
In other words there's no such a thing in C++ as "a function value". Functions are not values that you can assign to.
When you write
you are truly trying to create a variable of type
void(int). But such a thing doesn't exist, hence the error.The
static_casts don't work for fundamentally the same reason.As regards
function-to-(function)pointer decaying is happening.
fis truly of typefn_p1*.You can easily verify it by writing an invalid statement in
functionalin order to trigger a compiler error telling you what the type offis, like thisClangd answers this
which indirectly tells you that
fis of typefn_p1*, so you better write that instead offn_p1as the type of the parameter offunctional, at least for clarity (similarly to how you should prefer writingT*instead ofT[]as a parameter type in a function taking a c-style array ofTs).If you truly want to assign functions to variables, you should look at lambdas,
structs+operator(),std::function, and the topic of function objects in general.