Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing member function with all arguments to std::function

Tags:

c++

c++11

How can I create a std::function from member function without need for typing std::placeholders::_1, std::placeholders::_2, etc - I would like to "placehold" all arguments, saving only the object itself.

struct Foo{
  int bar(int,float,bool) {return 0;}
};
int baz(int,float,bool) {return 0;}
int main() {
  Foo object;
  std::function<int(int,float,bool)> fun1 = baz; // OK
  std::function<int(int,float,bool)> fun2 = std::bind(&Foo::bar, object); // WRONG, needs placeholders
}

I don't want to provide arguments at this stage, I just want to store function + object somewhere. For example I would like to have std::vector with both global functions and member functions. It was easy to do with FastDelegate (fastdelegate::MakeDelegate(object, &Class::function)).

I don't want to use lambda as it would require me to retype arguments as well. I just want old FastDelegate behaviour.

like image 802
Wojtek Avatar asked Oct 30 '13 19:10

Wojtek


People also ask

How can we pass arguments to functions in C++?

The call by value method of passing arguments to a function copies the actual value of an argument into the formal parameter of the function. In this case, changes made to the parameter inside the function have no effect on the argument. By default, C++ uses call by value to pass arguments.

How can we pass arguments to function?

Arguments are passed by value; that is, when a function is called, the parameter receives a copy of the argument's value, not its address. This rule applies to all scalar values, structures, and unions passed as arguments. Modifying a parameter does not modify the corresponding argument passed by the function call.

How many arguments can pass through a function?

Question 1: How many arguments is it possible to pass to a C++ function? Answer 1: When it comes to passing arguments to function, the maximum number of arguments that is possible to pass is 253 for a single function of the C++ programming language.

How do you pass a class function as an argument?

To pass an object as an argument we write the object name as the argument while calling the function the same way we do it for other variables. Syntax: function_name(object_name); Example: In this Example there is a class which has an integer variable 'a' and a function 'add' which takes an object as argument.


1 Answers

You can use function template which will deduce all member function parameter types, like this:

template<typename Obj, typename Result, typename ...Args>
auto make_delegate(const Obj &x, Result (Obj::*fun)(Args...)) -> // ...

And will return special delegate object, which will contain your object (or pointer to it) and just forward all passed arguments to member function of underlying object:

template<typename Obj, typename Result, typename ...Args>
struct Delegate
{
    Obj x;
    Result (Obj::*f)(Args...);

    template<typename ...Ts>
    Result operator()(Ts&&... args)
    {
        return (x.*f)(forward<Ts>(args)...);
    }
};

You will get following usage syntax:

function<int(int,float,bool)> fun = make_delegate(object, &Foo::bar);

Here is full example:

#include <functional>
#include <iostream>
#include <utility>

using namespace std;

struct Foo
{
    int bar(int x, float y, bool z)
    {
        cout << "bar: " << x << " " << y << " " << z << endl;
        return 0;
    }
};

int baz(int x, float y, bool z)
{
    cout << "baz: " << x << " " << y << " " << z << endl;
    return 0;
}

template<typename Obj, typename Result, typename ...Args>
struct Delegate
{
    Obj x;
    Result (Obj::*f)(Args...);

    template<typename ...Ts>
    Result operator()(Ts&&... args)
    {
        return (x.*f)(forward<Ts>(args)...);
    }
};

template<typename Obj, typename Result, typename ...Args>
auto make_delegate(const Obj &x, Result (Obj::*fun)(Args...))
    -> Delegate<Obj, Result, Args...>
{
    Delegate<Obj, Result, Args...> result{x, fun};
    return result;
}

int main()
{
    Foo object;
    function<int(int,float,bool)> fun[] =
    {
        baz,
        make_delegate(object, &Foo::bar) // <---- usage
    };
    for(auto &x : fun)
        x(1, 1.0, 1);
}

Output is:

baz: 1 1 1
bar: 1 1 1

Live Demo on Coliru

like image 54
Evgeny Panasyuk Avatar answered Oct 15 '22 02:10

Evgeny Panasyuk