std::function and std::bind: what are they, and when should they be used?
Asked Answered
W

5

185

I know what functors are and when to use them with std algorithms, but I haven't understood what Stroustrup says about them in the C++11 FAQ.

Can anyone explain what std::bind and std::function are, when they should be used, and give some examples for newbies?

Wirewove answered 7/7, 2011 at 11:43 Comment(0)
G
272

std::bind is for partial function application.

That is, suppose you have a function object f which takes 3 arguments:

f(a,b,c);

You want a new function object which only takes two arguments, defined as:

g(a,b) := f(a, 4, b);

g is a "partial application" of the function f: the middle argument has already been specified, and there are two left to go.

You can use std::bind to get g:

auto g = bind(f, _1, 4, _2);

This is more concise than actually writing a functor class to do it.

There are further examples in the article you link to. You generally use it when you need to pass a functor to some algorithm. You have a function or functor that almost does the job you want, but is more configurable (i.e. has more parameters) than the algorithm uses. So you bind arguments to some of the parameters, and leave the rest for the algorithm to fill in:

// raise every value in vec to the power of 7
std::transform(vec.begin(), vec.end(), some_output, std::bind(std::pow, _1, 7));

Here, pow takes two parameters and can raise to any power, but all we care about is raising to the power of 7.

As an occasional use that isn't partial function application, bind can also re-order the arguments to a function:

auto memcpy_with_the_parameters_in_the_right_flipping_order = bind(memcpy, _2, _1, _3);

I don't recommend using it just because you don't like the API, but it has potential practical uses for example because:

not2(bind(less<T>, _2, _1));

is a less-than-or-equal function (assuming a total order, blah blah). This example normally isn't necessary since there already is a std::less_equal (it uses the <= operator rather than <, so if they aren't consistent then you might need this, and you might also need to visit the author of the class with a cluestick). It's the sort of transformation that comes up if you're using a functional style of programming, though.

Gettysburg answered 7/7, 2011 at 11:54 Comment(8)
Also handy for callbacks to member functions: myThread=boost::thread(boost::bind(&MyClass::threadMain, this))Borsch
Nice explanation of bind. But what about std::function?Culdesac
Your pow example doesn't compile. Since pow is an overloaded function, you have to manually specify which overload. The binding can't leave it to be deduced by the caller of the resulting functor. E.g. std::transform(vec.begin(), vec.end(), out.begin(), std::bind((double (*)(double, int))std::pow, _1, 7));Stuffy
Very well explained, but sometimes std::bind comes together with the this usage as the 2nd argument. Can you please elaborate this use case?Douceur
@Mendes: If the function you bind is the member function of any class, you use this as a 2nd parameter and the 3rd parameters are placeholders.Storytelling
Also by "_1" you mean std::placeholders::_1. Took me a while to find out why this wasn't compiling.Condolent
I'm down voting everyone that explains c++ code with auto in their examples.Kellum
@Kellum And why is that? Not using auto here would be completely moronic. In the first example, say if f is int f(int,int,int), then g would have type _Bind<int(*(_Placeholder<1>,int,_Placeholder<2>))(int,int,int)>. Do you really want to write that in your code? Does that make anything clearer for the reader? I highly doubt that...Rap
C
67

One of the main use of std::function and std::bind is as more generelized function pointers. You can use it to implement callback mechanism. One of the popular scenario is that you have some function that is going to take long time to execute but you don't want to wait for it to return then you can run that function on separate thread and give it a function pointer that it will callback after it completes.

Here's a sample code for how to use this:

class MyClass {
private:
    //just shorthand to avoid long typing
    typedef std::function<void (float result)> TCallback;

    //this function takes long time
    void longRunningFunction(TCallback callback)
    {
        //do some long running task
        //...
        //callback to return result
        callback(result);
    }

    //this function gets called by longRunningFunction after its done
    void afterCompleteCallback(float result)
    {
        std::cout << result;
    }

public:
    int longRunningFunctionAsync()
    {
        //create callback - this equivalent of safe function pointer
        auto callback = std::bind(&MyClass::afterCompleteCallback, 
            this, std::placeholders::_1);

        //normally you want to start below function on seprate thread, 
        //but for illustration we will just do simple call
        longRunningFunction(callback);
    }
};
Chelsea answered 3/12, 2016 at 5:28 Comment(6)
This is a great answer. I have looked all over to find this answer. Thanks @ShitalShahCondolent
Could you add an explanation for why the binding helps make it safer?Swartz
My bad... I didn't intend to say it is more "safer". Normal function pointers are also typesafe however std::function is more generic to work with lambdas, context capture, member methods etc.Chelsea
bind(&MyClass::afterCompleteCallback, this, std::placeholders::_1) , 2 args for 1 in definition, void afterCompleteCallback(float result) , can explain this?Grafton
@nonock For function pointers of member functions, we need to pass "this" pointer as the first argument.Morceau
why do you need std::bind() and not just use something like: longRunningFunction(afterCompleteCallback); ?Sihun
R
15

std::bind was voted into library after proposal to include boost bind, primarily it is partial function specialization where-in you can fix few parameters and change others on fly. Now this is library way of doing lambdas in C++. As answered by Steve Jessop

Now that C++11 supports lambda functions I don't feel any temptation to use std::bind anymore. I would rather use currying (partial specialization) with language feature than library feature.

std::function objects are polymorphic functions. The basic idea is to be able to refer to all the callable objects interchangeably.

I would point you to these two links for further details:

Lambda functions in C++11: https://www.variadic.xyz/2011/10/12/c11-lambda-having-fun-with-brackets/

Callable entity in C++: https://www.variadic.xyz/2011/05/31/callable-entity/

Rosin answered 6/11, 2012 at 23:6 Comment(2)
std::bind never existed without lambdas - both of those features were introduced in C++11. We did have bind1st and bind2nd which were emaciated versions of C++11 bind.Stuffy
The nullptr.me domain doesn't exist any more.Astrix
F
6

I used it long time back to create a plugin thread pool in C++ ; Since the function was taking three parameters you can write like this

Suppose your method has the signature:

int CTask::ThreeParameterTask(int par1, int par2, int par3)

To create a function object to bind the three parameters you can do like this

// a template class for converting a member function of the type int function(int,int,int)
//to be called as a function object
template<typename _Ret,typename _Class,typename _arg1,typename _arg2,typename _arg3>
class mem_fun3_t
{
public:
    explicit mem_fun3_t(_Ret (_Class::*_Pm)(_arg1,_arg2,_arg3))
        :m_Ptr(_Pm) //okay here we store the member function pointer for later use
    {}

    //this operator call comes from the bind method
    _Ret operator()(_Class *_P, _arg1 arg1, _arg2 arg2, _arg3 arg3) const
    {
        return ((_P->*m_Ptr)(arg1,arg2,arg3));
    }
private:
    _Ret (_Class::*m_Ptr)(_arg1,_arg2,_arg3);// method pointer signature
};

Now, in order to bind the parameters, we have to write a binder function. So, here it goes:

template<typename _Func,typename _Ptr,typename _arg1,typename _arg2,typename _arg3>
class binder3
{
public:
    //This is the constructor that does the binding part
    binder3(_Func fn,_Ptr ptr,_arg1 i,_arg2 j,_arg3 k)
        :m_ptr(ptr),m_fn(fn),m1(i),m2(j),m3(k){}


        //and this is the function object 
        void operator()() const
        {
            m_fn(m_ptr,m1,m2,m3);//that calls the operator
        }
private:
    _Ptr m_ptr;
    _Func m_fn;
    _arg1 m1; _arg2 m2; _arg3 m3;
};

And, a helper function to use the binder3 class - bind3:

//a helper function to call binder3
template <typename _Func, typename _P1,typename _arg1,typename _arg2,typename _arg3>
binder3<_Func, _P1, _arg1, _arg2, _arg3> bind3(_Func func, _P1 p1,_arg1 i,_arg2 j,_arg3 k)
{
    return binder3<_Func, _P1, _arg1, _arg2, _arg3> (func, p1,i,j,k);
}

and here us how to call it

F3 f3 = PluginThreadPool::bind3( PluginThreadPool::mem_fun3( 
          &CTask::ThreeParameterTask), task1,2122,23 );

Note: f3(); will call the method task1->ThreeParameterTask(21,22,23);

For more gory details --> http://www.codeproject.com/Articles/26078/A-C-Plug-in-ThreadPool-Design

Footstall answered 14/2, 2014 at 6:0 Comment(0)
D
0

A std::function (aka lambda) is an object that contains executable code

#include <stdio.h>
#include <functional>
int main() {
  std::function<void ()> funcObj = []() {
    puts( "Code" );
  };

  funcObj();
}

After creating the function object, you can execute it any time later by using the normal funcObj() brackets syntax

You can "capture" parameters in the square brackets of the lambda, specify a return type, or specify that the lambda accepts arguments at invokation time in the template parameters

void plainFunction( string arg, int intVal ) {
  printf( "plainFunction running, string arg=`%s`, intVal=%d\n", arg.c_str(), intVal );
}

int intVal = 5;
std::function<void (string)> lambda2 = [intVal]( string arg ) {
  // Now say we want to pass that lambda call off to a normal function..
  plainFunction( arg, intVal ); // Pass arg from the function object arguments
  // and intVal from the lambda capture
};

// invokation of this lambda requires an argument to be passed
lambda2( "Just a normal string" ); // intVal was lambda captured

Outputs:

plainFunction running, string arg=Just a normal string, intVal=5

What std::bind does is mimic a lambda, only it is meant to create a lambda that invokes another existing function.

std::bind basically creates a std::function for later invokation

// std::bind is good for sticking arguments that you have around
// for a LATER call to a function with those arguments saved off
// eq to using a lambda
intVal = 6;
// Create a lambda that invokes plainFunction, with args as specified
std::function<void (string)> boundLambda = std::bind( plainFunction, std::placeholders::_1, intVal );

// Here std::placeholders_1 is used to say the lambda will
// accept 1 argument at invokation time
// intVal is saved off like in a lambda capture

boundLambda( "bound lambda call" );

Outputs:

plainFunction running, string arg=bound lambda call, intVal=6

You can use std::bind as a shortcut syntax for a lambda

std::bind just ties up some values that you have around in the code, and sticks them together with a function to invoke, into a function object, that you can invoke later

The short of it is, you don't usually need to use std::bind, you can use a raw lambda to achieve the same functionality

Decor answered 20/3, 2024 at 17:22 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.