Sign in to follow this  
dingojohn

Problems using boost::bind

Recommended Posts

dingojohn    159
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<std::string (void)> get_function and boost::function<void (std::string)> 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<void (std::string)> set_function, boost::function<std::string (void)> 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.

Share this post


Link to post
Share on other sites
jyk    2094
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.

Share this post


Link to post
Share on other sites
dingojohn    159
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<Signature>' to 'const int &'

Share this post


Link to post
Share on other sites
Toni Petrina    123
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.

Share this post


Link to post
Share on other sites
dingojohn    159
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.

Share this post


Link to post
Share on other sites
Toni Petrina    123
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.

Share this post


Link to post
Share on other sites
Toni Petrina    123
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.

Share this post


Link to post
Share on other sites
dingojohn    159
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<void, std::string> called set_function in the console. The function stored uses function composition through bind so that the console can call Variable( lexical_cast<int> (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<std::string, void> 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<std::string>( 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?

Share this post


Link to post
Share on other sites
Toni Petrina    123
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

Share this post


Link to post
Share on other sites
Julian90    736
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)

Share this post


Link to post
Share on other sites
dingojohn    159
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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this