Search code examples
c++functional-programminglambdac++11bind

Bind Vs Lambda?


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?


Solution

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