tags:

views:

55

answers:

1

I'm new to Boost, but not to functional programming, and I'm trying to see where Boost can help me out.

I have a list of 2D points, and I want to extract the minimum x coordinate. The Point class has a member function float x() const so I can use boost::mem_fn as follows:

boost::mem_fn(&Point::x)

But in order to use std::min_element, I need an object that supports bool operator()(Point const &, Point const &). Something like this fictional compare_by:

leftmostPoint = std::min_element(
    points.begin(), points.end(),
    boost::compare_by(boost::mem_fn(&Point::x)));

Can I use Boost to construct such a comparison, or do I need to do this myself?


Update: Here's my own implementation, but I'm still interested to see how Boost could've done this for me.

template<typename F>
class CompareBy {
    F const d_f;
    public:
        CompareBy(F f) : d_f(f) { }
        template<typename T>
        bool operator()(T const &a, T const &b) const {
            return d_f(a) < d_f(b);
        }
};

template<typename F>
CompareBy<F> compare_by(F f) {
    return CompareBy<F>(f);
}

Usage: as above, minus the boost:: namespace.

+4  A: 

I'm not aware of any boost construct similar to your Compare_by.
However, boost::bind can do the trick.

Point leftmostPoint = *std::min_element(points.begin(), points.end(),
   boost::bind(std::less<Point::type_x>(), 
       boost::bind( &Point::x, _1 ), boost::bind( &Point::x, _2 )));

Yeah, that's not pretty :/
Luckily, there is a syntax shortcut available, because function objects produced by boost::bind overload a lot of usual operator, like <, so you can do :

Point leftmostPoint2 = *std::min_element(points.begin(), points.end(),
boost::bind( &Point::x, _1 ) < boost::bind( &Point::x, _2 ));

But I think only C++0X's lambda can really achieve brevity and clarity :

Point leftmostPoint3 = *std::min_element(points.begin(), points.end(),
[](const Point& p1, const Point& p2){ return p1.x < p2.x; });
Thomas Petit