Skip to main content
gamedev.net
🔒 Locked

Problems using boost::bind

Started by dingojohn Aug 1, 2007 at 12:25 PM 9 replies 1.4k views
Original Post
dingojohn
dingojohn
Hello I've run into a problem when using boost::bind, and I cannot figure why it wont compile. I'm using bind to create function bindings for my console system, so that the console can set and get variables of a class without the classes depending on eachother. My console has a ConsoleItem which has a boost::function get_function and boost::function set_function. From the console I can call Add, which then creates a ConsoleItem with functions as argument: void Add(std::string name, boost::function set_function, boost::function get_function). I can then create a ConsoleItem doing this:
Console con;
con.Add("name", bind(&ClassWithVariable::Variable, &X, bind(lexical_cast<int, std::string>, _1 )), bind( lexical_cast<std::string, int>, bind(&ClassWithVariable::Variable, &X)) );
Where the function Variable is int Variable(void) and void Variable(int) -- get and set respectively. I can now get and set via the console using the name as identifier and pass a string as argument for setting and do a boost::lexical_cast when getting. The problem however is that I am lazy and therefor I to create functions for adding each of the item types I can so that the interface is more like this:



// one of these functions for each type I can add. 
// Possibly only named Add with different boost::function arguments
void AddInt(std::string name, boost::function<void (int)> set_function, boost::function<int (void)> get_function) {
   Add(name, boost::bind(set_function, boost::lexical_cast<int, std::string>, _1), boost::bind(boost::lexical_cast<std::string, int>, get_function)); // does not compile
} 

So that I can call add a console item like this:

Console con;
con.AddInt("hello", bind(&ClassWithVariable::Variable, &X, _1), bind(&ClassWithVariable::Variable, &X) );

The problem is, however, that the code with AddInt does not compile, and I have no idea why. Any help appreciated.
Zakwayda
Zakwayda
Quote:
Original post by dingojohn
The problem is, however, that the code with AddInt does not compile, and I have no idea why.
Can you post the error?

I only briefly glanced over your code, but I did notice that you (appear to) have overloaded member functions (the two versions of Variable) of which you're taking the address. Perhaps this is the cause of the problem.
dingojohn
dingojohn
It does the same when I do not use overloaded member functions.

However, here is the error:

error C2664: 'std::string (const int &)' : cannot convert parameter 1 from 'boost::function' to 'const int &'
Toni Petrina
Toni Petrina
You have an error in last section, to be more specific

boost::bind(boost::lexical_cast<std::string, int>, get_function)


you bind function object to first parameter of lex_cast which is string.
So... Muira Yoshimoto sliced off his head, walked 8 miles, and defeated a Mongolian horde... by beating them with his head?

Documentation? "We are writing games, we don't have to document anything".
dingojohn
dingojohn
Quote:
Original post by Toni Petrina
You have an error in last section, to be more specific

boost::bind(boost::lexical_cast<std::string, int>, get_function)


you bind function object to first parameter of lex_cast which is string.


Really? The function object takes no arguments and returns an int. I was quite sure it would be bound and then executed when the bound function is executed. Composition is quite possible, and I actually do it without problems with the old add function:

Console con;con.Add("name", bind(&ClassWithVariable::Variable, &X, bind(lexical_cast<int, std::string>, _1 )), bind( lexical_cast<std::string, int>, bind(&ClassWithVariable::Variable, &X)) );


It should be the same, considering that the ClassWithVariable.Variable is int Variable ( void )

Feel free to tell me if I misunderstood what you said or how bind works.
Toni Petrina
Toni Petrina
Hmm, now I confused myself. Why don't you try compiling this.
boost::bind(set_function, boost::lexical_cast<int, std::string>, _1);boost::bind(boost::lexical_cast<std::string, int>, get_function);


Now check which statement doesn't compile. I'm gonna recheck myself tomorrow, gotta get some sleep.
So... Muira Yoshimoto sliced off his head, walked 8 miles, and defeated a Mongolian horde... by beating them with his head?

Documentation? "We are writing games, we don't have to document anything".
Toni Petrina
Toni Petrina
Actually, ofcourse it doesn't compile! It isn't same code. You bind the binder object at the wrong place. You don't get the same effect.

I don't get what exactly do you want to do so I'll try to figure out more tomorrow.
So... Muira Yoshimoto sliced off his head, walked 8 miles, and defeated a Mongolian horde... by beating them with his head?

Documentation? "We are writing games, we don't have to document anything".
dingojohn
dingojohn
What I am trying to do is quite simple. I want to create function bindings using the lexical_cast, so that the console internally can handle the functions with strings as argument.

void ClassWithVariable::Variable(int); is stored as a function called set_function in the console. The function stored uses function composition through bind so that the console can call Variable( lexical_cast (string) ) with set_function(string);

Just like that, the get function uses an approach that is quite like it:
int ClassWithVariable::Variable(void) is stored as a function called get_function in the console It is done with boost::lexical_cast again, so that calling the get_function in the console results in calling boost::lexical_cast( Variable() );.

It works like a charm with the Console.Add I have provided, however doing it with Console.AddInt doesn't work. All I've done is created a function that accepts another argument, and then converts it to what I want it to be. To me the composition looks right, due to the fact that I do what I do when callingthe Console.Add.

Any ideas?
Toni Petrina
Toni Petrina
As far as I can see, problem is in the first part, originally you had
bind(&ClassWithVariable::Variable, &X, bind(lexical_cast<int, std::string>, _1 ))

now you have
boost::bind(set_function, boost::lexical_cast<int, std::string>, _1)set_function=bind(&ClassWithVariable::Variable, &X, _1)


shouldn't code be like this?
boost::bind(set_function, boost::bind(boost::lexical_cast<int, std::string>, _1))


That is why I said that your composition isn't right
So... Muira Yoshimoto sliced off his head, walked 8 miles, and defeated a Mongolian horde... by beating them with his head?

Documentation? "We are writing games, we don't have to document anything".
Julian90
Julian90
Quote:
Really? The function object takes no arguments and returns an int. I was quite sure it would be bound and then executed when the bound function is executed. Composition is quite possible, and I actually do it without problems with the old add function:


IIRC (I haven't checked) this problem is known and documented in the boost.lambda documentation, to work around it you need to wrap the function object in boost::lambda::protect or something similar (I think, as I said I haven't checked and I'm not to sure about the specifics)
dingojohn
dingojohn
I changed the AddInt function to

void AddInt(std::string name, boost::function<void (int)> set_function, boost::function<int (void)> get_function) 		{			Add(name, boost::bind(set_function, boost::bind(boost::lexical_cast<int, std::string>, _1)), boost::bind(boost::lexical_cast<std::string, int>, boost::bind(get_function)));		}


and now it seems to work. Thanks for the help, and nice catch Toni Petrina. It's really appreciated.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.