Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why use std::bind over lambdas in C++14?

Before C++11 I used boost::bind or boost::lambda a lot. The bind part made it into the standard library (std::bind) the other part became part of the core language (C++ lambdas) and made the use of lambdas a lot easier. Nowadays, I hardly use std::bind, since I can do almost anything with C++ lambdas. There's one valid use-case for std::bind that I can think of:

struct foo {   template < typename A, typename B >   void operator()(A a, B b)   {     cout << a << ' ' << b;   } };  auto f = bind(foo(), _1, _2); f( "test", 1.2f ); // will print "test 1.2" 

The C++14 equivalent for that would be

auto f = []( auto a, auto b ){ cout << a << ' ' << b; } f( "test", 1.2f ); // will print "test 1.2" 

Much shorter and more concise. (In C++11 this does not work yet because of the auto parameters.) Is there any other valid use case for std::bind beating the C++ lambdas alternative or is std::bind superfluous with C++14?

like image 785
Ralph Tandetzky Avatar asked Jun 28 '13 10:06

Ralph Tandetzky


People also ask

Why do we need std :: bind?

Use of std::bind in STL algorithms As std::bind acts as a functional adaptor and gives the a new function objects, hence it is very usefull with many STL algorithms. For example, We have a list of numbers and we want to count the numbers which are multiple of 5.

Why is it important to bind a function to its arguments C++?

Bind function with the help of placeholders helps to manipulate the position and number of values to be used by the function and modifies the function according to the desired output.

What is the point of std :: function?

Class template std::function is a general-purpose polymorphic function wrapper. Instances of std::function can store, copy, and invoke any Callable target -- functions, lambda expressions, bind expressions, or other function objects, as well as pointers to member functions and pointers to data members.


2 Answers

Scott Meyers gave a talk about this. This is what I remember:

In C++14 there is nothing useful bind can do that can't also be done with lambdas.

In C++11 however there are some things that can't be done with lambdas:

  1. You can't move the variables while capturing when creating the lambdas. Variables are always captured as lvalues. For bind you can write:

    auto f1 = std::bind(f, 42, _1, std::move(v)); 
  2. Expressions can't be captured, only identifiers can. For bind you can write:

    auto f1 = std::bind(f, 42, _1, a + b); 
  3. Overloading arguments for function objects. This was already mentioned in the question.

  4. Impossible to perfect-forward arguments

In C++14 all of these possible.

  1. Move example:

    auto f1 = [v = std::move(v)](auto arg) { f(42, arg, std::move(v)); }; 
  2. Expression example:

    auto f1 = [sum = a + b](auto arg) { f(42, arg, sum); }; 
  3. See question

  4. Perfect forwarding: You can write

    auto f1 = [=](auto&& arg) { f(42, std::forward<decltype(arg)>(arg)); }; 

Some disadvantages of bind:

  • Bind binds by name and as a result if you have multiple functions with the same name (overloaded functions) bind doesn't know which one to use. The following example won't compile, while lambdas wouldn't have a problem with it:

    void f(int); void f(char); auto f1 = std::bind(f, _1, 42); 
  • When using bind functions are less likely to be inlined

On the other hand lambdas might theoretically generate more template code than bind. Since for each lambda you get a unique type. For bind it is only when you have different argument types and a different function (I guess that in practice however it doesn't happen very often that you bind several time with the same arguments and function).

What Jonathan Wakely mentioned in his answer is actually one more reason not to use bind. I can't see why you would want to silently ignore arguments.

like image 101
BertR Avatar answered Sep 23 '22 20:09

BertR


Sometimes it is just less code. Consider this:

bool check(int arg1, int arg2, int arg3) {   return ....; } 

Then

wait(std::bind(check,a,b,c)); 

vs lambda

wait([&](){return check(a,b,c);}); 

I think that bind is easier to read here compared to the lambda which looks like a https://en.wikipedia.org/wiki/Brainfuck

like image 40
AlexTheo Avatar answered Sep 22 '22 20:09

AlexTheo