c++11: Templated wrapper function
Asked Answered
I

2

6

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

Inefficiency answered 25/8, 2014 at 22:44 Comment(2)
I didn't know this syntax with the -> . Thank you for this. It worked:)!Inefficiency
You should be passing like this: func(std::forward<Args>(args)...)Doc
T
14

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;
}
Townspeople answered 25/8, 2014 at 22:46 Comment(5)
@Smith_61: Very well.Townspeople
This worked:) Thank you very much. Unfortunately i didn't know result_of.Inefficiency
In C++14 you can also forget about result_of and friends completely and use return type deduction :)Solicitude
What does using && in F&&(Args&&...) do btw?Chunchung
@0x499602D2: It does what it says on the box. It gives you the same type that is later used in the actual call.Townspeople
R
7

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

Race answered 25/8, 2014 at 22:50 Comment(3)
Don't you need the whole std::forward shebang for the trailing return type too, lest you end up using the return type from the wrong func overload, or something?Solicitude
Thank you for this answer. It works great:) Also thanks for the c++14 version. Kerrek SB gave a working version first, so i marked his post as accepted. But also thanks to you! (you also got a vote)Inefficiency
@Solicitude yes we do need the "shebang", updated, thanks for the note.Race

© 2022 - 2024 — McMap. All rights reserved.