Question

Let's say I have

struct Value { int foo(); };
size_t *begin = ...,
       *end   = ...;

If I want to sort a bunch of Value indices in C++03, I have to write something tedious like this:

struct Comparator
{
    Value *data;
    Comparator(Value *data) : data(data) { }
    bool operator()(size_t a, size_t b)
    { return data[a].foo() < data[b].foo(); }
};
sort(begin, end, Comparator(data));

Is there any way to write this more neatly, preferably in 1 line, with Boost (perhaps with Boost.Lambda)?

Was it helpful?

Solution

Using Boost.Phoenix (which is the preferred lambda library of Boost):

#include <boost/phoenix/phoenix.hpp>

{
    // for bind and ref
    using namespace boost::phoenix;

    using namespace boost::phoenix::placeholders;
    std::sort(begin, end
              , bind(&Value::foo, ref(data)[arg1]) < bind(&Value::foo, ref(data)[arg2]) );
}

An alternative is to use LocalFunction which essentially lets you do what you're doing (passing a local type to std::sort, which is not allowed for C++03) in a portable fashion. Usage should be (code is untested for this one though):

#include <boost/local_function.hpp>

{
    int BOOST_LOCAL_FUNCTION(const bind& data, std::size_t lhs, std::size_t rhs)
    {
        return data[lhs].foo() < data[rhs].foo();
    } BOOST_LOCAL_FUNCTION_NAME(comparator)

    std::sort(begin, end, comparator);
}

OTHER TIPS

No.

Boost.Lambda works best when dealing with overloaded operators. Once you bring a named function call into things, Boost.Lambda becomes much less useful in making code more concise and easy to read. You have to start using function binders and other such things.

And the fact that you're using the lambda parameters as indices (rather than the values being indexed) probably screws things up as far as using operator[] in the Boost.Lambda library too.

You could make a Boost.Lambda equivalent of this. But it wouldn't be anything I would call "neat", and the "1 line" would be extremely long.

There's a reason why C++11 introduced lambdas into the language instead of just incorporating Boost.Lambda into the standard library.

Oh, and don't forget: Boost.Lambda is generally considered obsolete. Use Boost.Phoenix instead. Granted, it's not going to help you any more than Lambda does.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top