Search code examples
c++lambdac++11functor

Creating functor from lambda expression


I would like to know if it is possible to create an actual functor object from a lambda expression. I don't think so, but if not, why?

To illustrate, given the code below, which sorts points using various policies for x and y coordinates:

#include <vector>
#include <functional>
#include <algorithm>
#include <iostream>

struct Point 
{ 
    Point(int x, int y) : x(x), y(y) {}
    int x, y; 
};

template <class XOrder, class YOrder> 
struct SortXY : 
    std::binary_function<const Point&, const Point&, bool>
{
    bool operator()(const Point& lhs, const Point& rhs) const 
    {
        if (XOrder()(lhs.x, rhs.x))
            return true;
        else if (XOrder()(rhs.x, lhs.x))
            return false;
        else
            return YOrder()(lhs.y, rhs.y);
    }          
};

struct Ascending  { bool operator()(int l, int r) const { return l<r; } };
struct Descending { bool operator()(int l, int r) const { return l>r; } };

int main()
{
    // fill vector with data
    std::vector<Point> pts;
    pts.push_back(Point(10, 20));
    pts.push_back(Point(20,  5));
    pts.push_back(Point( 5,  0));
    pts.push_back(Point(10, 30));

    // sort array
    std::sort(pts.begin(), pts.end(), SortXY<Descending, Ascending>());

    // dump content
    std::for_each(pts.begin(), pts.end(), 
                  [](const Point& p) 
                  {
                     std::cout << p.x << "," << p.y << "\n"; 
                  });
}

The expression std::sort(pts.begin(), pts.end(), SortXY<Descending, Ascending>()); sorts according to descending x values, and then to ascending y values. It's easily understandable, and I'm not sure I really want to make use of lambda expressions here.

But if I wanted to replace Ascending / Descending by lambda expressions, how would you do it? The following isn't valid:

std::sort(pts.begin(), pts.end(), SortXY<
    [](int l, int r) { return l>r; }, 
    [](int l, int r) { return l<r; }
>());

Solution

  • This problem arises because SortXY only takes types, whereas lambdas are objects. You need to re-write it so that it takes objects, not just types. This is basic use of functional objects- see how std::for_each doesn't take a type, it takes an object.