Breaking News
Loading...
Sunday 4 May 2014

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

21:31

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 =
    cpplinq::from_array(boxes)
    >> 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) {
    match(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>
    boost::shared_ptr<T>
    make_shared_ptr(std::shared_ptr<T> ptr)
    {
    return boost::shared_ptr<T>(ptr.get(),
    [ptr](T*) mutable { ptr.reset(); });
    }

    template <typename T>
    std::shared_ptr<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




0 comments:

Post a Comment

 
Toggle Footer