Why cant i assign a function to function pointer? - c++

While doing my homework i decided to use function pointer as a callback function. I am not going to post the whole homework here as it is too large. Here i wrote small test code to illustrate the error i am getting.
#include <iostream>
void function()
{
std::cout << "test";
}
int main()
{
void* functionPtr(int) = function;
functionPtr();
}
I am getting error C2059: syntax error: '=' here void* functionPtr(int) = function;. If i hower my mouse over = sign it says next: "function functionPtr cannot be initialized". If i change that to ...
void* functionPtr();
functionPtr = function;
...i will be getting error C2659: '=': function as left operand.
Am i using function pointers wrong way?
I use Visual Studio 2019 btw.
Thank you for any help.

This isn't the right syntax. You declare a function, not a function pointer.
Here's how a function pointer is declared:
void(*functionPtr)(int);
As you noticed, the star is beside the name. If there is no parenthesis, the star will apply to the return type and not the name.
Or with a trailing return type:
auto(*functionPtr)(int) -> void;
Also, your function called function don't take an int as parameter. So it should be like this:
void(*functionPtr)() = function;

You got the types wrong. There is no int parameter for in function and you missed a *. Your declare functionPtr as a function. For a function pointer you need:
void(*functionPtr)() = function;
// ^--- "pointer to function"
However, since C++11, using function pointers got much simpler, as you can do
using functionPtrType = void(*)();
functionPtrType p = function;
Or
using functionPtrType = decltype(&function);
functionPtrType p = function;
which has a tiny disadvantage of not making it obvious that a function pointer is involved. The advantage is that it wont break when you change the signature of function.
On the other hand, once you use decltype (and you do not need the type of the function pointer elsewhere) you can as well shorten it to:
decltype(&function) functionPtr = function;
Eventually, this is already avoiding so much to spell out the type that you can simply use auto:
auto functionPtr = &function;

To create a pointer to a function, you need to use parentheses to override the normal binding of the *. void *f() means f is a function returning a pointer to void. To instead get a pointer to a function returning void, you need void (*f)();
So in your case, the code would look something like void (*functionPtr)() = function;

Related

Call a function from its address via a templated function

Assuming I have the runtime memory address of a function in an Application and I know the return type of said function, is it possible to call the function, knowing the functions return type, its arguments and calling convention, using a variadic template?
The templated function has to support both void and non-void return types. Due to the fact that we are dealing with function pointers, the compiler shouldn't complain, despite return ptr.
I thought about doing something like this:
template<typename ReturnType, typename Address, typename... Args>
ReturnType function_caller(Address address, Args... args)
{
ReturnType(*ptr)(Args...) = address;
return ptr(args...);
}
int main()
{
auto address = 0x100;
auto address2 = 0x200;
function_caller<void>(&address, 1, 1); // Function with return type void.
int result = function_caller<int>(&address2, 1, 2, 3.f, "hello");
// result should contain the int value we received by calling the function at 0x200
}
Sadly the compiler throws the error C2440: It can't convert the Address "address" to 'ReturnType (__cdecl *)(int,int)'
I would really appreciate your help with this problem. I know i could just split this wrapper into 2 functions: one for void calls and one for non-void calls, but i hope there is a more elegant, template-supported solution.
Thank you and have a nice day!
the answer is yes, but doing it with variadic template is dangerous .
to enforce the compiler to cast the address to a function pointer you need to use reinterpret_cast or a c cast .
note : you are improperly casting an integral address to a pointer because you are really trying to cast the address of the variable containing the address to the pointer not the address itself !
so this line :
function_caller<void>(&address, 1, 1); // Function with return type void.
should be :
function_caller<void>(address, 1, 1); // Function with return type void.
and always use the address type as uintptr_t which will fit for any address available for the architecture (64 bit or 32)
but doing so with variadic template isn't safe at all . the reason is that the function have particular arguments type like this :
int fn(std::string& str, const char* ptr, uint64_t& i);
but when you cast with variadic template the compiler will deduce the types from the arguments passed however some conversions may be required !
so in your current version :
int i;
function_caller<int>(0x15216516, "str", "ptr", i);
the compile will assume that the function signature is something like :
int fn(const char*, const char*, int); // wrong types means stack corruptions and undefined behaviors
also see this :
std::string to_string(std::string_view v);
function_caller<std::string>(0x15216516, "str"); // wrong the compiler won't convert the string literal for you and the function will end up with a dangling view
function_caller<std::string>(0x15216516, std::string("str")); // wrong again there is no conversion from std::string to std::string_view here
so it is really reliable only to specify the whole function type and use that to cast the address like what boost.dll does

Casting lambda with non-void return type to function pointer

I am trying to cast a lambda function to a function pointer. However, the cast fails when the lambda has a non-void return type. Details see the code snippet.
Is it possible to cast fun2 into a generic function pointer which I can save for later usage?
Update: My intention is to cast all kinds of functions to a "generic function pointer" which can be saved in a std::map. Upon usage, I will cast it back to its original function type.
#include <iostream>
int fun3() { return 1; }
int main(int argc, char *argv[]) {
typedef void (*voidFunctionType)(void);
// Case 1: lambda, return type void
auto fun1 = []() { std::cout << "hello" << std::endl; };
// -> compiles
auto casted_fun1 = (voidFunctionType)fun1;
// Case 2: lambda, return type int
auto fun2 = []() { std::cout << "world" << std::endl; return -1;};
// -> error: invalid cast from type ‘main(int, char**)::<lambda()>’ to type ‘voidFunctionType {aka void (*)()}’
auto casted_fun2 = (voidFunctionType)fun2;
// Case 3: free function, return type int -> compiles
auto casted_fun3 = (voidFunctionType)fun3;
return 0;
}
The problem is that you are using C-style explicit casts. These are notoriously dangerous.
Here in this case the problem is that fun3 (in contrast to fun2) already decays to a function pointer of type int(*)().
You then cast it to void(*)(). This works because the C-style cast will try to do different C++ cast expressions until one works. In particular it will also try a reinterpret_cast.
reinterpret_cast<voidFunctionType>(fun3)
works, because reinterpret_cast can cast any function pointer to any other function pointer.
However, you are not allowed to call the function through the obtained pointer. Doing so causes your program to have undefined behavior. As you can see this cast is of very limited use and dangerous if you are not aware of it.
Don't use C-style casts, use static_cast<voidFunctionType>(fun3) instead and you will get the appropriate compile-time error in both cases.
You cannot use a function (whether free function or lambda) that returns one type as if it returned another (or no) type. Casting the lambda that returns int to void(*)() therefore doesn't make sense.
If you really want to save arbitrary function pointers you can make the lambda cast work by first converting it to a function pointer and then casting it to the destination function pointer type with a reinterpret_cast. I would still not use C style casts, because the reinterpret_cast will at least make it clear what kind of cast you are intending to do:
auto casted_fun2 = reinterpret_cast<voidFunctionType>(+fun2);
The unary + is a common trick to force lambda to function pointer conversion. Note however also that only lambdas without capture can be converted to function pointers.
As I explained above though, you must cast the pointer back to its original type before calling it, so you need to store the type information somewhere. I am not sure how you intend to do that, but you probably need to implement some extended version of std::function, see e.g. this question for how std::function does it.

Function pointer vs Function reference

In the code below, function-pointer and what i considered as "function-reference" seems to have identical semantics:
#include <iostream>
using std::cout;
void func(int a) {
cout << "Hello" << a << '\n';
}
void func2(int a) {
cout << "Hi" << a << '\n';
}
int main() {
void (& f_ref)(int) = func;
void (* f_ptr)(int) = func;
// what i expected to be, and is, correct:
f_ref(1);
(*f_ptr)(2);
// what i expected to be, and is not, wrong:
(*f_ref)(4); // i even added more stars here like (****f_ref)(4)
f_ptr(3); // everything just works!
// all 4 statements above works just fine
// the only difference i found, as one would expect:
// f_ref = func2; // ERROR: read-only reference
f_ptr = func2; // works fine!
f_ptr(5);
return 0;
}
I used gcc version 4.7.2 in Fedora/Linux
UPDATE
My questions are:
Why function pointer does not require dereferencing?
Why dereferencing a function reference doesn't result in an error?
Is(Are) there any situation(s) where I must use one over the other?
Why f_ptr = &func; works? Since func should be decayed into a pointer?
While f_ptr = &&func; doesn't work (implicit conversion from void *)
Functions and function references (i.e. id-expressions of those types) decay into function pointers almost immediately, so the expressions func and f_ref actually become function pointers in your case. You can also call (***func)(5) and (******f_ref)(6) if you like.
It may be preferable to use function references in cases where you want the &-operator to work as though it had been applied to the function itself, e.g. &func is the same as &f_ref, but &f_ptr is something else.
"Why function pointer does not require dereferencing?"
Because the function identifier itself is actually a pointer to the function already:
4.3 Function-to-pointer conversion
§1 An lvalue of function type T can be converted to an rvalue of type “pointer to T.” The result is a pointer to the function.
"Why dereferencing a function reference doesn't result in an error?"
Basically you can look at defining a reference as defining an alias (alternative name). Even in the standard in 8.3.2 References in part addressing creating a reference to an object, you will find:
"a reference can be thought of as a name of an object."
So when you define a reference:
void (& f_ref)(int) = func;
it gives you the ability to use f_ref almost everywhere where it would be possible to use func, which is the reason why:
f_ref(1);
(*f_ref)(4);
works exactly the same way as using the func directly:
func(1);
(*func)(4);
See here.
The address-of operator acts like you would expect, as it points to a function but cannot be assigned. Functions are converted to function pointers when used as rvalues, which means you can dereference a function pointer any number of times and get the same function pointer back.
As there are good answers from other people here, there is no answer explaining why f_ptr = &&func; does not work. When you apply the addressof operator & to a variable/function, you get its address. The adress itself is an r-value/a temporary variable. You cannot take the address of a temporary.
But it seems that there is a type error. The message implicit conversion from void* is very compiler specific for this code. I guess you are using GCC/Clang. GCC/Clang offers the ability to take the address of labels like &&label. The resulting value is of type void*. Other compilers will output something like cannot take address of temporary or invalid syntax. When using these compilers this kind of error could have been hidden without any warning in special circumstances:
int main() {
int foo = 42;
foo:;
void* a = &foo; // take the address of a variable/function
void* b = &&foo; // take the address of a label
std::cout << *(int*)a << '\n';
goto *b;
};
But who would name everything the same?

Who can help me explain the use of typedef in C++?

I am so confused with this code in the book :
typedef int (*healthCalcFunc) (const GameCharacter&)
and I understand that
typedef double* PDouble, means the word PDouble can be used to declare a pointer to double.
But I can't figure out the meaning of typedef int (*healthCalcFunc) (const GameCharacter&)
Is there anyone can help me to explain this?
Thanks in advance
:)
typedef int (*healthCalcFunc) (const GameCharacter&);
It introduces a name called healthCalcFunc for a type which describes a function-pointer, taking one parameter of type const GameCharacter& and returning an int.
So this means, if you've a function as:
int some_function(const GameCharacter&)
{
//...
}
Then you can create a pointer-object which would point to the above function as:
healthCalcFunc pfun = some_function;
and then use pfun in place of some_function as:
some_function(args); /normal call
pfun(args); //calling using function pointer
//it is exactly same as the previous call
And benefit with this approach is that you can pass around pfun (or some_function) to other function as:
void other_function(healthCalcFunc pfun)
{
//..
pfun(args); //invoke the function!
//..
}
healthCalcFunc pfun = some_function;
other_function(some_function);
other_function(pfun);
Here other_function will use the function pointer to invoke the function. That way, next time you can pass another function matching the function signature to other_function and other_function will invoke that another function instead.
In cases like this, operator precedence tends to get in the way.
What this creates is an alias (named healthCalcFunc) for the type "pointer to a function taking a reference to a const GameCharacter as its parameter and returning an int".
int: return type
(*healthCalcFunc): Pointer to function -- must be in parens to bind the * to the name instead of the preceding int, which would declare a function returning a pointer instead of the desired pointer to a function.
(const GameCharacter &): the parameter list for the type of function this will point at.
It's a function pointer - hopefully your book will have explained these somewhere; if not, your favourite search engine should be able to point you in the right direction.
That is typedef for a function pointer for functions which return int and take const GameCharacter& as an argument.
You can create a function pointer using healthCalcFunc hp = &MyFunc; then use it as int n = (*hp)(GameCharacter());. Here MyFunc will have this signature: int MyFunc(const GameCharecter&);.
This is a function type definition. At first glance, it's strange, but you'll get used to it. basically, what it says is, define a type named healthCalcFunc, whose return value is an integer, and takes a constant GameCharacter reference as its only argument.
In general, the form of a function pointer declaration is as follows:
typedef return_type (*new_function_typename)(typeof_arg1, typeof_arg2, ...);
And you can use it like this:
new_function_typename functor;
functor = some_other_functions_name;
// or
functor = dlsym(dlopen_handle, "some_function_name"); // for dynamic loading
int retval = functor(arg1, arg2);

Cryptic C++ "thing" (function pointer)

What is this syntax for in C++? Can someone point me to the technical term so I can see if I find anything in my text?
At first I thought it was a prototype but then the = and (*fn) threw me off...
Here is my example:
void (*fn) (int&,int&) = x;
It can be rewritten to
typedef void (*T) (int&, int&);
T fn = x;
The 2nd statement is obvious, which should have solved that = x; question. In the 1st statement, we make T as a synonym as the type void(*)(int&, int&), which means:
a pointer to a function ((*…))
returning void
and taking 2 arguments: int&, int&.
That is a function pointer to a function taking two int reference parameters, which returns nothing. The function pointer is called fn and is being assigned the value in x.
This declares and initializes a function pointer.
The name of the variable is fn, and it points to a function with the following signature:
void pointedToFunction(int&, int&)
The variable fn is initialized to the value contained in x.
The pointed-to function can be called using the following syntax:
int a;
int b;
(*fn)(a,b);
This is equivalent to
int a;
int b;
pointedToFunction(a,b);
Function pointer.
http://www.newty.de/fpt/intro.html#what
^ Okay source for a beginner. :-)
This is a pointer to a function that takes two references to ints and returns void.
That seems like a function pointer to a method that takes two integer references and does not return anything. The pointer will be named fn. You are assigning it to the address of x, which is hopefully a function that matches this description.
It's a function pointer to a function that takes 2 integers as arguments and returns void. x must be a function name.
It's a function pointer variable that gets initialized to the stuff to the right of =.
The function type could be written like this:
typedef void func_t(int&,int&);
The function pointer than would be:
typedef func_t *fn_t;
With these definitions the variable declaration would be much clearer:
fn_t fn = ...;
Wikipedia page with a few links on the subject: http://en.wikipedia.org/wiki/Function_pointer