Jump to content
  • Advertisement
Sign in to follow this  
nreyntje

Unity Boost lambda, sorting objects?

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

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by nreyntje
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));
}
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!