Reputation: 11
I'm trying to call functions through their pointers. Compiling this code, I get errors saying that expressions of type void cannot be converted to other types, but I check whether the function returns a void or not before calling the function. Is there another way that I can accomplish this?
class FuncBase {
public:
FuncBase(string n, string ret, string arg1, string arg2): name(n), retval(ret), a1(arg1), a2(arg2) {}
string getName() const { return name; }
string getRet() const { return retval; }
string getA1() const { return a1; }
string getA2() const { return a2; }
virtual void call() = 0;
private:
string name, retval, a1, a2;
};
template <typename ret, typename arg1, typename arg2>
class Func: public FuncBase {
public:
Func(string n, string r, string ar1, string ar2, ret(*fc)(arg1, arg2)):
FuncBase(n, r, ar1, ar2), func(fc) {}
void call() {
arg1 ar1;
arg2 ar2;
cout << "You chose the " << getName() << " function" << endl;
cout << "Enter a " << getA1() << ": ";
cin >> ar1;
cout << "Enter a " << getA2() << ": ";
cin >> ar2;
if (getRet() != "void") {
ret val = (*func)(ar1, ar2);
cout << getName() << " returned " << val << endl;
}
else (*func)(ar1, ar2);
cout << endl;
}
private:
// pointer to function
ret(*func)(arg1, arg2);
};
Upvotes: 0
Views: 3110
Reputation: 4752
I assume that 'arg1', 'arg2', and 'ret' are all template parameters. Given that, even if the runtime path the code will take you to (*func)(ar1, ar2)
, the compiler still has to compile ret val = (*func)(ar1, ar2);
, which makes no sense for functions that return void. I assume this is giving you the error. Can you provide us with a bit more of your code?
Edit: Okay now that I see what you are trying to do, you'll need something like this to execute void and non-void functions, with different behavior for each:
int foo(){ return 5; }
void bar(){}
struct executor
{
template <typename T>
void exec( T (*func)())
{
T ret = (*func)();
cout << "Non-void function called, returned " << ret << endl;
}
void exec( void (*func)())
{
(*func)();
cout << "void function called" << endl;
}
};
int main()
{
executor ex;
ex.exec(foo);
ex.exec(bar);
return 0;
}
Upvotes: 1
Reputation: 612954
For template instantiations where this fails, func
is a function pointer that receives two arguments and has void
return type. That is ret
is void
. A function with a void return type does not return anything. Naturally you cannot read the return value of an invocation of (*func)()
because you said that there was no return value.
Even though the branch that reads the return value won't get executed, it still needs to compile and pass the static type checking. The fundamental issue here is that the calls to *func()
are dealt with at compile time and are subject compile time static type checking.
This Stack Overflow question covers the exact same problem as you and the accepted answer shows how to deal with the issue
Upvotes: 4