Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this possible without template specialization?

Tags:

c++

templates

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;
};
like image 367
SingerOfTheFall Avatar asked Apr 15 '26 15:04

SingerOfTheFall


2 Answers

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

like image 137
Piotr Skotnicki Avatar answered Apr 18 '26 07:04

Piotr Skotnicki


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>();
}
like image 34
ForEveR Avatar answered Apr 18 '26 05:04

ForEveR



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!