Bind Vs Lambda?

2019-01-04 09:05发布

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?

6条回答
等我变得足够好
2楼-- · 2019-01-04 09:19

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).

查看更多
贪生不怕死
3楼-- · 2019-01-04 09:22

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.

查看更多
聊天终结者
4楼-- · 2019-01-04 09:23

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.

查看更多
狗以群分
5楼-- · 2019-01-04 09:32

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 :)

查看更多
一纸荒年 Trace。
6楼-- · 2019-01-04 09:32

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.

查看更多
疯言疯语
7楼-- · 2019-01-04 09:34

C++0x lambdas essentially replace bind. There is nothing you can bind that you can't recreate a trivial wrapper lambda to achieve the same. std::tr1::bind will go the way of std::bind1st, etc once lambda support is wide spread. Which is good, because for some reason most programmers have a hard time getting their head around bind.

查看更多
登录 后发表回答