0

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);
}; 
user1394518
  • 11
  • 1
  • 4
  • 3
    What is `getRet()`? Where is `func` declared? – Greg Hewgill May 14 '12 at 19:55
  • 6
    When asking a question about an error message, always post the exact error message, along with the line number that it's complaining about. – Oliver Charlesworth May 14 '12 at 19:56
  • I'm going to assume that `func` is a type that returns `void`. Even if you "know" that it doesn't return `void` (based on that `if`) the compiler will enforce strict type-checking. – Stephen Newell May 14 '12 at 19:56
  • 3
    Why are you putting `delete this;` in your destructors? – Blastfurnace May 14 '12 at 20:16
  • 1
    Just so you know, there's an `std::is_void` that you can use to check instead of keeping track of it in strings. – chris May 14 '12 at 20:27
  • possible duplicate of [Check at Compile-Time if Template Argument is void](http://stackoverflow.com/questions/9625526/check-at-compile-time-if-template-argument-is-void) – David Gelhar May 15 '12 at 13:52
  • Possible duplicate of [What does "Incompatible types: void cannot be converted to ..." mean?](https://stackoverflow.com/questions/42369301/what-does-incompatible-types-void-cannot-be-converted-to-mean) – Stephen C May 05 '19 at 07:43

2 Answers2

4

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

Community
  • 1
  • 1
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
1

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;
}
Rollie
  • 4,391
  • 3
  • 33
  • 55