Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using template for return value. how to handle void return?

Tags:

I have structure for storing callback function like this:

template<class T>
struct CommandGlobal : CommandBase
{
    typedef boost::function<T ()> Command;
    Command comm;

    virtual T Execute() const
    {
        if(comm)
            return comm();
        return NULL;
    }
};

Seems like it should work fine except when T is void because the Execute function wants to return a value..

What is the best solution to this problem?

Thanks!

like image 552
Sebastian Edwards Avatar asked Jul 22 '10 04:07

Sebastian Edwards


People also ask

Can I use return for a method of the return type void?

Any method declared void doesn't return a value. It does not need to contain a return statement, but it may do so.

How do you return a value from a void function?

A void function cannot return any values. But we can use the return statement. It indicates that the function is terminated. It increases the readability of code.

What happens when we return a value from a function whose return type is void?

Void functions are created and used just like value-returning functions except they do not return a value after the function executes. In lieu of a data type, void functions use the keyword "void." A void function performs a task, and then control returns back to the caller--but, it does not return a value.

Is return legal in a void function?

Yes, you can return from a void function.


2 Answers

This answer is based off this fun-fact: In a function returning void, you can return any expression of which the type is void.

So the simple solution is:

virtual T Execute() const
{
    if (comm) 
        return comm();
    else
        return static_cast<T>(NULL);
}

When T = void, the last return statement is equivalent to return;.


However, I feel this is bad design. Is NULL meaningful for every T? I don't think so. I would throw an exception:

virtual T Execute() const
{
    if (comm)
        return comm();
    else
        throw std::runtime_error("No function!")
}

However, this is done automatically by Boost, so your code becomes the much cleaner:

virtual T Execute() const
{
    return comm();
}

You could then add additional functionality, such as:

bool empty(void) const
{
    return !comm; // or return comm.empty() if you're the explicit type
}

So the user can check if it can be called prior to calling it. Of course at this point, unless your class has additional functionality you've left out for the sake of the question, I see no reason not to just use boost::function in the first place.

like image 103
GManNickG Avatar answered Dec 02 '22 20:12

GManNickG


If it's just the return statement, this should do the trick:

virtual T Execute() const
{
    if(comm)
        return comm();
    return T();
}

If there's more to it, specialize the template for void.

like image 23
sbi Avatar answered Dec 02 '22 20:12

sbi