Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++11: Templated wrapper function

I try to create a general wrapper function which takes any function as argument and also their parameters. Just something like the std::thread constructor.

My current code is:

#include <iostream>

using namespace std;

template<typename FUNCTION, typename... ARGS>
void wrapper(FUNCTION&& func, ARGS&&... args)
{
    cout << "WRAPPER: BEFORE" << endl;
    auto res = func(args...);
    cout << "WRAPPER: AFTER" << endl;
    //return res;
}

int dummy(int a, int b)
{
    cout << a << '+' << b << '=' << (a + b) << endl;
    return a + b;
}

int main(void)
{
    dummy(3, 4);
    wrapper(dummy, 3, 4);
}

The wrapper function itself works. It calls the given function object (std::function, functor or just a "normal" function) with the given arguments. But i also like to return its return value.

This should work with the removed return-statement, but unfortunately i dont know how to declare the wrapper functions return type.

I tried many things (e.g. with decltype), but nothing worked. My question is now, how i get the following code running?

#include <iostream>

template<typename FUNCTION, typename... ARGS>
??? wrapper(FUNCTION&& func, ARGS&&... args)
{
    cout << "WRAPPER: BEFORE" << endl;
    auto res = func(args...);
    cout << "WRAPPER: AFTER" << endl;
    return res;
}

int dummy(int a, int b)
{
    cout << a << '+' << b << '=' << (a + b) << endl;
    return a + b;
}

int main(void)
{
    dummy(3, 4);
    cout << "WRAPPERS RES IS: " << wrapper(dummy, 3, 4) << endl;
}

I think the code should work, except for the ???.

Thank you for any ideas

Regards Kevin

like image 597
Kevin Meier Avatar asked Aug 25 '14 22:08

Kevin Meier


2 Answers

Use std::result_of:

template <typename F, typename ...Args>
typename std::result_of<F &&(Args &&...)>::type wrapper(F && f, Args &&... args)
{
    return std::forward<F>(f)(std::forward<Args>(args)...);
}

In C++14 you can use the result_of_t alias:

template <typename F, typename ...Args>
std::result_of_t<F &&(Args &&...)> wrapper(F && f, Args &&... args)
{
    return std::forward<F>(f)(std::forward<Args>(args)...);
}

Or you can use return type deduction:

template <typename F, typename ...Args>
decltype(auto) wrapper(F && f, Args &&... args)
{
    std::cout << "before\n";
    auto && res = std::forward<F>(f)(std::forward<Args>(args)...);
    std::cout << "after\n";
    return res;
}
like image 116
Kerrek SB Avatar answered Oct 19 '22 22:10

Kerrek SB


You can use decltype with the C++11 auto trailing return type :

template<typename FUNCTION, typename... ARGS>
auto wrapper(FUNCTION&& func, ARGS&&... args) -> decltype(func(std::forward<ARGS>(args)...))

Live demo


And in C++14, simply do :

template<typename FUNCTION, typename... ARGS>
decltype(auto) wrapper(FUNCTION&& func, ARGS&&... args)

Live demo

like image 21
quantdev Avatar answered Oct 20 '22 00:10

quantdev