Sunday, May 04, 2014

Fun with Lambdas: C++14 Style (part 2)

Look at some interesting examples of C++11/14 lambdas and how they interact with other language features and libraries. I hope to find some time to add some explanations. See part 1 if you missed it.

  • Associative containers and lambdas
    std::set<int, std::function<bool(int, int)>> 
      numbers([](int i, int j) { return i < j; });
  • Recursive Lambdas (see Creating recursive lambdas and returning them too!)
    auto make_fibo() 
      return [](int n) {
        std::function<int(int)> recurse;
        recurse = [&](int n){ 
           return (n<=2)? 1 : recurse(n-1) + recurse(n-2); 
        return recurse(n);
  • Composable list manipulation (e.g., cpplinq, narl, LEESA)
    Box boxes[] = { ... };
    int sum_of_weights = 
      >> where([](const Box & box) { 
           return box.color == Color.RED;
      >> select([](const Box & box) {
           return box.get_weight();
      >> sum();
  • Overloaded Lambdas
    template <class... F>
    struct overload : F... {
      overload(F... f) : F(f)... {}  
    template <class... F>
    auto make_overload(F... f) {
      return overload<F...>(f...);   
    auto f = 
        make_overload([](int i) { /* print */ },
                      [](double d) { /* print */ });
    f(10); // int 
    f(9.99); // double
  • Type Switch (simple pattern matching) (see type_switch.cpp and this paper)
    struct Base { 
      virtual ~Base() {} 
    struct Derived : Base {};
    template <class Poly>
    void test(Poly& p) {  
        [](int i)             { cout << "int";       },
        [](std::string &)     { cout << "string";    },
        [](Derived &)         { cout << "Derived";   },     
        [](Base &)            { cout << "Base";      },    
        otherwise([](auto x)  { cout << "Otherwise"; })
    Derived d;
    Base &b = d;
    std::string cpptruths = "C++ Truths";
    boost::any something = cpptruths;
    test(10);        // int
    test(cpptruths); // string
    test(something); // string
    test(b);         // Derived
    test(9.99);      // Otherwise
  • Converting shared_ptr between boost and std (see StackOverflow)
    template <typename T>
    make_shared_ptr(std::shared_ptr<T> ptr) 
      return boost::shared_ptr<T>(ptr.get(), 
        [ptr](T*) mutable { ptr.reset(); });
    template <typename T>
    make_shared_ptr(boost::shared_ptr<T> ptr)
      return std::shared_ptr<T>(ptr.get(), 
        [ptr](T*) mutable { ptr.reset(); });
  • In-place parameter pack expansion 
    template <class... T>
    void foreach(T... args) 
      bool b[] = { [=](){ 
        std::cout << args << "\n"; 
        return true; 
      }()... }; 
    foreach(10, 20.2, true);
  • Memoization (see original)
    template <typename ReturnType, 
              typename... Args>
    auto memoize(ReturnType (*func)(Args...))
        std::map<std::tuple<Args...>, ReturnType> cache;
        return ([=](Args... args) mutable  
            std::tuple<Args...> t(args...);
            if (cache.find(t) == cache.end())                
              std::cout << "not found\n";
              cache[t] = func(args...);
            return cache[t];
  • Finally, slides


Amber said...

should `sum_of_weights` have been `count_of_weights`? (that'd make it a bit trivial). Or perhaps `count()` is the mistake

(I surely hope count doesn't sum)

Amber said...

The memoization example is nice and succinct, but it strikes me as significantly less advanced than others I've seen years ago on your blog, and even somewhat less featured than e.g. Herb's popular example.

Is there a reason you prefer this one, beyond the clarity of exposition?

Seth said...

I really like the overload example. Something like that should be in the standard library (though more general, so it works for any callable entity, not just inheritable classes.)

The 'In-place parameter pack expansion' example relies on function arguments being evaluated in a certain order. Instead you can avoid no_op(...) and do:
{bool b[] = {[=]() { cout << args << "\n"; return true; }()...};}

Nagy said...

Here is the original discussion for make_shared_ptr:

Sumant Tambe said...

@Amber and @Seth: Right. Thanks. I fixed the code.

y121516 said...

The Overloaded Lambdas code is ill-formed.
It work on Clang, but it is error occurred on GCC.
And behavior of GCC is correct.

Please see a entry and well-formed code written by @fimbul11

Lee said...

Nice couple of posts, Sumant. Made me want to dig into this a bit more. I've done a bit of digging, and have some more yet to do. I did find a way to compose lambdas (and, by extension, functions).

I've got a blog post on that at

Affity Solutions said...

Thanks for your ideas. You can also find the details on Affity Solutions, at the C Developers. The main object of the Affity Solutions is to provide quality web services and is among the few software development company in Nagpur.

Leopoldo said...

Muy buena.
Pagina de códigos basicos:

learn programming C++ said...

Thanks for sharing this information. Python is an easy language for beginners, because there's less of an emphasis on syntax. So, if you forget your parentheses or misplace a few semicolons, it shouldn't trip you up as much as it might if you were coding in a different language.If you wanna try to check out more about learn programming C++

RKM IT Institute said...

C and C++ Live Project Training in Delhi- RKM IT Institute is a skill enhancement coaching center that makes engineers hot property in the booming IT industry. We offer C and C++ Programming Concepts & Languages training by experts.