Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I wrap a std::function and have easy access to its return and argument types?

I'm trying to do something that simplifies to the following:

#include <functional>
#include <initializer_list>
#include <vector>

template <typename Ret, typename... Args>
struct func_wrapper
{
public:
    using Func = std::function<Ret(Args...)>;

    Ret operator()(Args && ...args)
    {
        return _impl(std::forward<Args>(args)...);
    }

    void another_function(int another_arg, Args && ...args) { }
    /// and so on

private:
   Func _impl;
};

func_wrapper<void(int, float)> f;


Basically, I want to make a type that wraps a std::function and adds some other functionality for my application. Inside my type, I would like to be able to use the return type Ret and argument parameter pack Args freely in the class interface. However, when I try to compile the above with gcc 8.3, I get an error:

<source>: In instantiation of 'struct func_wrapper<void(int, float)>':
<source>:20:32:   required from here
<source>:9:45: error: function returning a function
     using Func = std::function<Ret(Args...)>;
                                             ^
<source>:11:9: error: function returning a function
     Ret operator()(Args && ...args)

I'm not sure what to make of that error. Is there a straightforward way to do what I want?

like image 247
Jason R Avatar asked Sep 01 '25 15:09

Jason R


1 Answers

@max66's answer does a great job showing how to avoid the issue you're running into. For more info about what specifically isn't working here, take a look at how you've parameterized your template and how you've used it:

template <typename Ret, typename... Args> struct func_wrapper {
     ...
};

This means that your template expects that you'll instantiate it by writing something like

func_wrapper<int, float> // Function taking a float and returning an int
func_wrapper<void, int, float> // Function taking a float and an int and returning void
func_wrapper<int> // Function taking no arguments and returning void

Notice, in particular, that func_wrapper<T> means that Ret will be T and the function will take no arguments.

As a result, when you write

func_wrapper<void(int, float)>

you're saying "a function representing something that takes no arguments and returns a function that takes in an int and a float and returns void," which isn't what you wanted. That's why you're getting the error about returning a function being illegal.

like image 53
templatetypedef Avatar answered Sep 05 '25 02:09

templatetypedef