Bind Vs Lambda?
Solution 1
As you said, bind and lambdas don't quite exactly aim at the same goal.
For instance, for using and composing STL algorithms, lambdas are clear winners, IMHO.
To illustrate, I remember a really funny answer, here on stack overflow, where someone asked for ideas of hex magic numbers, (like 0xDEADBEEF, 0xCAFEBABE, 0xDEADDEAD etc.) and was told that if he were a real C++ programmer he would simply have download a list of English words and use a simple one-liner of C++ :)
#include <iterator>
#include <string>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
int main()
{
using namespace boost::lambda;
std::ifstream ifs("wordsEn.txt");
std::remove_copy_if(
std::istream_iterator<std::string>(ifs),
std::istream_iterator<std::string>(),
std::ostream_iterator<std::string>(std::cout, "\n"),
bind(&std::string::size, _1) != 8u
||
bind(
static_cast<std::string::size_type (std::string::*)(const char*, std::string::size_type) const>(
&std::string::find_first_not_of
),
_1,
"abcdef",
0u
) != std::string::npos
);
}
This snippet, in pure C++98, open the English words file, scan each word and print only those of length 8 with 'a', 'b', 'c', 'd', 'e' or 'f' letters.
Now, turn on C++0X and lambda :
#include <iterator>
#include <string>
#include <algorithm>
#include <iostream>
#include <fstream>
int main()
{
std::ifstream ifs("wordsEn.txt");
std::copy_if(
std::istream_iterator<std::string>(ifs),
std::istream_iterator<std::string>(),
std::ostream_iterator<std::string>(std::cout, "\n"),
[](const std::string& s)
{
return (s.size() == 8 &&
s.find_first_not_of("abcdef") == std::string::npos);
}
);
}
This is still a bit heavy to read (mainly because of the istream_iterator business), but a lot simpler than the bind version :)
Solution 2
C++0x lambdas are monomorphic, while bind can be polymorphic. You cannot have something like
auto f = [](auto a, auto b) { cout << a << ' ' << b; }
f("test", 1.2f);
a and b must have known types. On the other hand, tr1/boost/phoenix/lambda bind allows you to do this:
struct foo
{
typedef void result_type;
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"
Note that the types A and B are not fixed here. Only when f is actually used these two will be deduced.
Solution 3
The C++ 0x lamdba syntax is more readable than the bind syntax. Once you get into more than 2-3 level bind, you code becomes pretty much unreadable and difficult to maintain. I would prefer the more intuitive lambda syntax.
Solution 4
One of the benefits of lambdas is they are way more useful when you need to add a little big of logic on top of an existing function.
With bind, you are forced to create a new function/method/functor even if the logic is only ever needed in this one place. You need to come up with an appropriate name and it can make the code less understandable as it potentially makes you split up related logic.
With lambda, you can add the new logic inside the lambda (but are not forced to if it makes sense to create a new callable).
Solution 5
I think it's more a matter of taste. People that quickly grasp new technologies, or are familiar with functional programming will probably prefer lambda syntax, while more conservative programmers will definitively prefer bind, as it is more in par with the traditional C++ syntax.
Such a decision should be made in coordination with the people that will be working with the code, probably through a majority vote.
Which doesn't change the fact however, that lambda syntax is much more powerful and cleaner.
Khaled Alshaya
I am member of the team responsible for the design, implementation and maintenance of the financial systems of the largest energy company in the world! If I could allocate some spare time, I spend it mostly on learning new technologies. C++ was the first programming language I learned and I still love using it for personal projects.
Updated on July 15, 2022Comments
-
Khaled Alshaya almost 2 years
I have a question about which style is preferred: std::bind Vs lambda in C++0x. I know that they serve -somehow- different purposes but lets take an example of intersecting functionality.
Using
lambda
:uniform_int<> distribution(1, 6); mt19937 engine; // lambda style auto dice = [&]() { return distribution(engine); };
Using
bind
:uniform_int<> distribution(1, 6); mt19937 engine; // bind style auto dice = bind(distribution, engine);
Which one should we prefer? why? assuming more complex situations compared to the mentioned example. i.e. What are the advantages/disadvantages of one over the other?
-
pranavsharma over 14 yearsPeople in a team keep changing. Code readability is very important esp. for future maintenance programmers. Hence we should go with whichever solution that offers more readability and between lamdba and bind, lamda definitely takes the cake.
-
Khaled Alshaya over 14 yearsAlthough the two pieces of code don't do the same thing, I got your point of view very clearly :)
-
KitsuneYMG over 14 years+1. I had to close a vector of FILE* in a dtor. Instead of being able to use a lambda
[](FILE* f) { if(f) fclose(f); }
I had to create a named function and use that. The function appeared in theprivate
part of the class and was thus separated by many lines from thefor_each
call -
Admin over 14 yearsthe lambda should be: [](const std::string& s) -> bool
-
Khaled Alshaya over 14 years@Beh Tou Cheh I think the type should be deduced if lambda consists of
return <expression>;
only(as Thomas did). -
Alex S about 13 yearsWhy not just declare the lambda with explicitly-typed parameters? That would be a vast improvement over the bind solution shown above. Also, if you have more complex functionality that you want to reuse, lambda is still better than bind, since it doesn't require a struct, even if you want to bind state into the functor:
template<...>foo(A a, B b, int state){ cout ... << state; } ... auto f = [](const char* a, float b){ foo(a, b, 42); };
. -
MSalters about 13 years@Marcelo Cantos: The statement to prove was that "C++0x lambdas are monomorphic", precisely because you must declare the lambda with explicitly-typed parameters.
-
Alex S about 13 years@MSalters: The question was (roughly): "Which is better?" I'm not sure how proving that C++0x lambdas are monomorphic answers the question.
-
dv_ about 13 years@Marcelo Cantos: It shows a difference between the two. AraK asked about differences and benefits/drawbacks of bind vs. lambda.
-
Alex S about 13 yearsWhich part of the question is about differences, as opposed to benefits or preference? Even the title uses "vs", which suggests a contest.
-
Thomas Eding over 12 yearsAnd if you can use the same
f
with differing argument types, does the compiler give a type error? If so, then both are monomorphic. It's just thatlambda
has manifest typing, whereasbind
uses type inference. -
dv_ over 12 years@trinithis: It does not give a type error, since f is a functor with a templated call operator.
-
p12 over 10 yearsIn C++14 even this difference will disappear -- a lambda could be declared as
[](auto x){}
-
Fozi almost 10 yearsYou don't need a
bind
here. You can just sayauto f = foo();
. -
Andreas Haferburg about 9 yearsDisagree.
[this](){Type* this_too = this; run([this_too](){this_too->f();});}
is neither readable nor intuitive. -
Drew Dormann almost 8 yearsWhile this answer wasn't correct at the time it was posted, it is accurate for C++14. The link in the comment above confirms this now.
-
Thomas Eding almost 8 yearsAdmittedly I think new lines would help your counterexample. New lines would not help much with bind.
-
c z almost 3 yearsPersonal opinion anyway. Should be a comment, not an answer.
-
c z almost 3 yearsA member function must be at least 2 pointers because it must store a function pointer, and
this
, plus at least 1 more value for meta-data such as the number of arguments. The lambda is 1 pointer because it points to this data, not because it's been magicked away.