Let's say I need to make a class that accepts a function pointer, stores it, and then runs it. Let's also assume that the function that this class accepts can either return void, or cReturnValue; there are also other requirements and template arguments in my real code, which are irrelevant to the question.
Now, if the return type is void, I need to simply run the function. If the return type is cReturnValue, I need to run it, get the result, and use it. Is it possible to handle both cases in a single template, without using partial specialization?
template< typename Function, typename ReturnType > class Executor
{
public:
Executor(Function f) : _f(f) {}
void run()
{
//I know this will not work, but is this possible somehow?
if(std::is_same<ReturnType, void>::value)
{
_f();
}
else if(std::is_same<ReturnType, cReturnValue>::value)
{
cReturnValue val = _f();
//do some stuff with val
}
}
private:
Function _f;
};
Use tag-dispatching:
template <typename> struct tag {};
template <typename Function, typename ReturnType>
class Executor
{
public:
Executor(Function f) : _f(f) {}
void run()
{
run(tag<ReturnType>{});
}
private:
void run(tag<cReturnValue>)
{
cReturnValue val = _f();
}
void run(tag<void>)
{
_f();
}
Function _f;
};
DEMO
I think you cannot do such thing with single template. But you can use SFINAE for this. Something like this is very simple way to do this:
private:
template<typename R>
typename std::enable_if<std::is_same<R, void>::value>::type run_()
{
_f();
}
template<typename R>
typename std::enable_if<!std::is_same<R, void>::value>::type run_()
{
ReturnType val = _f();
// do some stuff with val
}
and run will be just
void run()
{
run_<ReturnType>();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With