Problems using boost::bind

Started by
9 comments, last by dingojohn 16 years, 8 months ago
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.
Advertisement
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.
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 &'
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".
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.
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".
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".
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?
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".
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)

This topic is closed to new replies.

Advertisement