# Unity Boost lambda, sorting objects?

This topic is 3651 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Note: this is a related thread but I could post there: http://www.gamedev.net/community/forums/topic.asp?topic_id=503958 I'm new to boost lambda and am trying to sort a vector of objects, but it won't compile.. Can anybody explain to me why please? Thanks! /* class I'm trying to sort */ class component_info { public: cell* comp; grid_bag_contraints cnstr; int space1; int space2; int preff; // delegates, makes lambda expressions easier :) int cnstr_off() { return cnstr.off; }; int cnstr_len() { return cnstr.len; }; int cnstr_space1() { return cnstr.space1; }; int cnstr_space2() { return cnstr.space2; }; int cnstr_ins1() { return cnstr.ins1; }; int cnstr_ins2() { return cnstr.ins2; }; float cnstr_weight() { return cnstr.weight; }; component_info(): comp(NULL), space1(0), space2(0) { cnstr = grid_bag_contraints(); preff = 0; }; }; void main() { vector<component_info> component_infos(10); sort(component_infos.begin(), component_infos.end(), bind(&component_info::cnstr_len, _1) < bind(&component_info::cnstr_len, _2)); }

##### Share on other sites
Quote:
 Original post by nreyntjeNote: this is a related thread but I could post there:http://www.gamedev.net/community/forums/topic.asp?topic_id=503958I'm new to boost lambda and am trying to sort a vector of objects, but itwon't compile..Can anybody explain to me why please? Thanks!/* class I'm trying to sort*/ class component_info { public: cell* comp; grid_bag_contraints cnstr; int space1; int space2; int preff; // delegates, makes lambda expressions easier :) int cnstr_off() { return cnstr.off; }; int cnstr_len() { return cnstr.len; }; int cnstr_space1() { return cnstr.space1; }; int cnstr_space2() { return cnstr.space2; }; int cnstr_ins1() { return cnstr.ins1; }; int cnstr_ins2() { return cnstr.ins2; }; float cnstr_weight() { return cnstr.weight; }; component_info(): comp(NULL), space1(0), space2(0) { cnstr = grid_bag_contraints(); preff = 0; };};void main() { vector component_infos(10); sort(component_infos.begin(), component_infos.end(), bind(&component_info::cnstr_len, _1) < bind(&component_info::cnstr_len, _2));}
Your code is a little hard to follow ([ source ] tags would help), but it doesn't look to me like you're actually using boost::lambda anywhere in this example.

In order to create a lambda expression, you need to use one of the lambda placeholders (AFAIK, at least), which you're not doing (you're using _1 and _2, but in this context those are bind placeholders, not lambda placeholders).

I'm not sure off the top of my head whether or how the comparison in your example can be expressed using boost::lambda - perhaps someone else can clarify that. There are plenty of (perhaps easier) alternatives though, for example a named free function, a free or member overload of operator<(), or a function object that overloads the () operator.

##### Share on other sites
My boost::lambda fu is weak, I generally stick to binds and explicit function composition, but I think the problem is that the lambda library can't deduce the return type of function objects produced by bind.

See lambda.overriding_deduced_return_type in the documentation.

I'm pretty sure that you just need to wrap the binds in the ret<T>() adaptor.

##### Share on other sites
First off all, thanx for the reply!
but you left my confused..

In http://www.boost.org/doc/libs/1_37_0/doc/html/lambda/s03.html#id3397831
I found that
"bind(foo, _1, _2)"
is called a "bind expression" and not a lambda expression..my mistake..

But I have some questions:

"bind(&component_info::cnstr_len, _1)"
is a unary functiod right?

"bind(&component_info::cnstr_len, _2)"
is a binary functiod rigth?

and than
"bind(&component_info::cnstr_len, _1) < bind(&component_info::cnstr_len, _2)"
is also a binary functiod right?

##### Share on other sites
Quote:
 "bind(&component_info::cnstr_len, _1) < bind(&component_info::cnstr_len, _2)"is also a binary functiod right?
When the compiler sees the above expression, it goes looking for a non-member overload of operator<() whose argument types are compatible with the return types of the two bind expressions. It can't find such an overload, so a compiler error is generated. (Or so I assume - it would probably be a good idea to post the actual error.)

std::sort() is expecting a function object as the third argument: an object that can be invoked using the syntax expression(...). The lambda library functions return such objects, but since you're not actually invoking any of the boost::lambda functions, that doesn't really help you at all here.

What it kind of looks like to me is that you're expecting C++ to construct a 'generic' lambda expression for you here, but that's not going to happen (C++ doesn't have built-in support for lambda expressions - boost::lambda is quite handy, but it's basically a very complicated workaround, and will only work if you use the syntax that it requires).

##### Share on other sites
It is also possible that you have a const correctness issue: your getters are not const, and this causes an error in below simplified code (since you didn't provide the grid_bag_contraints class) which compiles fine otherwise. In any case, if I'm not mistaken, the comparison functions/objects should always guarantee not to modify what is being compared.

(Also note that the getter isn't really necessary, since you apparently can bind class members too.)

#include <boost/lambda/lambda.hpp>#include <boost/lambda/bind.hpp>#include <vector>using namespace std;using namespace boost::lambda;class component_info {public:    //cell* comp;    //grid_bag_contraints cnstr;    int space1;    int space2;    int preff;    // delegates, makes lambda expressions easier :)    /*int cnstr_off() { return cnstr.off; };    int cnstr_len() { return cnstr.len; };    int cnstr_space1() { return cnstr.space1; };    int cnstr_space2() { return cnstr.space2; };    int cnstr_ins1() { return cnstr.ins1; };    int cnstr_ins2() { return cnstr.ins2; };    float cnstr_weight() { return cnstr.weight; };    */    int get_space1() const { return space1; }    component_info(): /*comp(NULL),*/ space1(0), space2(0)    {        //cnstr = grid_bag_contraints();        preff = 0;    }};int main() {    vector<component_info> component_infos(10);    sort(component_infos.begin(), component_infos.end(),        bind(&component_info::get_space1, _1) < bind(&component_info::get_space1, _2));    sort(component_infos.begin(), component_infos.end(),        bind(&component_info::space1, _1) < bind(&component_info::space1, _2));}

##### Share on other sites
EDIT: I think victor has it. It looks like < may be sufficently overloaded in the boost lambda library to not need all of those wrappers. That's good to know. I've only used it to get _1 and _2 in simple expressions.

Okay, now that the workday is winding down, I can give a bit more thought to this. The basic problem you're running into is the one jyk has pointed out: < is not creating a functor. It's just an operator, and there's no overload for the templated functors generated by bind.

Fortunately, with a couple more adaptors we can do this:

boost::bind(  std::less<int>(),  boost::bind(&component_info::cnstr_len,_1),  boost::bind(&component_info::cnstr_len,_2));

So, now we have two binary functors produced by bind, that pass their result to std::less's arguments. And we need one more bind to wrap this up. Whee!

The final functor has the the operator we need:

bool operator()(const component_info&, const component_info&).

##### Share on other sites
Quote:
 The basic problem you're running into is the one jyk has pointed out: < is not creating a functor. It's just an operator, and there's no overload for the templated functors generated by bind.

boost.bind documentation claims otherwise: the operators are overloaded since version 1.33

##### Share on other sites
Both methods are good to know!
I'll never write have to write custom functiods again!
Great!

##### Share on other sites
The original code looks perfectly correct.
You probably confused boost::bind with boost::lambda::bind.

• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 9
• 34
• 16
• 11
• 11
• ### Forum Statistics

• Total Topics
634122
• Total Posts
3015646
×