Hi all, I've just started using boost::bind and found the following problem: class Handler { public: bool Test1(std::string sComponent); bool Test2(std::string sComponent, std::string sAddress); }; void Test() { std::vector<Handler> v; // This compiles std::string a, b; std::for_each(v.begin(), v.end(), boost::bind(&Handler::Test1, _1, a)); // This doesn't compile //std::for_each(v.begin(), v.end(), // boost::bind(&Handler::Test2, _1, _2, a, b)); } Environment: boost 1.32, VC8, WinXP. Any ideas? Thanks, Oleg.
On Thu, 28 Jul 2005 13:22:28 +1200, "Oleg Smolsky"
I've just started using boost::bind and found the following problem:
class Handler { public: bool Test1(std::string sComponent); bool Test2(std::string sComponent, std::string sAddress); };
void Test() { std::vector<Handler> v;
// This compiles std::string a, b; std::for_each(v.begin(), v.end(), boost::bind(&Handler::Test1, _1, a));
This creates a functor with one argument, _1, which calls Handler::Test1 with _1 as this and a as argument 1 of Test1.
// This doesn't compile //std::for_each(v.begin(), v.end(), // boost::bind(&Handler::Test2, _1, _2, a, b));
This creates a functor with two arguments, _1 and _2, which calls Handler::Test2 with _1 as this, _2 as argument 1 of Test2, a as argument 2 of Test2 and b as argument 3 of Test2. But Test2 only has two arguments, and for_each only takes a functor with one argument. I think what you want is: std::for_each(v.begin(), v.end(), boost::bind(&Handler::Test2, _1, a, b)); To create a functor with one argument, _1, which calls Handler::Test2 with _1 as this, a as argument 1 of Test2 and b as argument 2 of Test2. Hope that helps, Dave. -- Dave Slutzkin Melbourne, Australia daveslutzkin@fastmail.fm
Hello Dave, Stuart, Dave Slutzkin wrote on 28/07/2005 at 6:21 p.m.:
std::for_each(v.begin(), v.end(), boost::bind(&Handler::Test1, _1, a));
This creates a functor with one argument, _1, which calls Handler::Test1 with _1 as this and a as argument 1 of Test1. Right.
I think what you want is: std::for_each(v.begin(), v.end(), boost::bind(&Handler::Test2, _1, a, b)); To create a functor with one argument, _1, which calls Handler::Test2 with _1 as this, a as argument 1 of Test2 and b as argument 2 of Test2. Right, that's exactly what I needed. Thanks.
// This doesn't compile //std::for_each(v.begin(), v.end(), // boost::bind(&Handler::Test2, _1, _2, a, b));
This creates a functor with two arguments, _1 and _2, which calls Handler::Test2 with _1 as this, _2 as argument 1 of Test2, a as argument 2 of Test2 and b as argument 3 of Test2. But Test2 only has two arguments, and for_each only takes a functor with one argument. This is very confusing.... Let me paraphrase your explanation: I was trying to feed an extra argument to bind, which takes parameters in this fashion: boost::bind(function, this, arg1, arg2, arg3, etc)
Right? If yes, what's the exact meaning of _1, _2 placeholders? Also, how does that mash with functions vs methods? Best regards, Oleg.
On 7/29/05, Oleg Smolsky
Hello Dave, Stuart,
Dave Slutzkin wrote on 28/07/2005 at 6:21 p.m.:
std::for_each(v.begin(), v.end(), boost::bind(&Handler::Test1, _1, a));
This creates a functor with one argument, _1, which calls Handler::Test1 with _1 as this and a as argument 1 of Test1. Right.
I think what you want is: std::for_each(v.begin(), v.end(), boost::bind(&Handler::Test2, _1, a, b)); To create a functor with one argument, _1, which calls Handler::Test2 with _1 as this, a as argument 1 of Test2 and b as argument 2 of Test2. Right, that's exactly what I needed. Thanks.
// This doesn't compile //std::for_each(v.begin(), v.end(), // boost::bind(&Handler::Test2, _1, _2, a, b));
This creates a functor with two arguments, _1 and _2, which calls Handler::Test2 with _1 as this, _2 as argument 1 of Test2, a as argument 2 of Test2 and b as argument 3 of Test2. But Test2 only has two arguments, and for_each only takes a functor with one argument. This is very confusing.... Let me paraphrase your explanation: I was trying to feed an extra argument to bind, which takes parameters in this fashion: boost::bind(function, this, arg1, arg2, arg3, etc)
Right?
If yes, what's the exact meaning of _1, _2 placeholders? Also, how does that mash with functions vs methods?
Best regards, Oleg.
When using boost.bind, a method is effectively treated as a function
with an unstated first parameter (i.e. this). So, if we have the
following declarations:
struct A
{
void AMethod(std::string const& a, std::string const& b);
};
void AFunction(A object, std::string const& a, std::string const& b);
std::vector<A> vecOfA;
std::string s1, s2;
Then the following are both correct:
std::for_each(vecOfA.begin(), vecOfA.end(), boost::bind(&A::AMethod,
_1, s1, s2));
std::for_each(vecOfA.begin(), vecOfA.end(), boost::bind(&AFunction,
_1, s1, s2));
In both cases, boost::bind creates a function object that has an
operator() with a signature like that shown below:
struct
Hello Stuart, Stuart Dootson wrote on 29/07/2005 at 11:30 a.m.:
When using boost.bind, a method is effectively treated as a function with an unstated first parameter (i.e. this). So, if we have the following declarations:
struct A { void AMethod(std::string const& a, std::string const& b); };
void AFunction(A object, std::string const& a, std::string const& b); Right, that makes sense.
Think about if you contructed a function object by hand:
struct FuncObj { FuncObj(std::string const& str1, std::string const& str2) : str1_(str1), str2_(str2) {}
void operator()(A object) { AFunction(object, str1_, str2_); }
std::string str1_; std::string str2_; };
std::for_each(vecOfA.begin(), vecOfA.end(), FuncObj(s1, s2));
You can see that the string arguments are supplied when you construct the function object, while the A parameter is passed into the function object when it is called, and passed through to the intended function. Right, I get it. Thank you for the in-depth explanation!
Best regards, Oleg.
On Fri, 29 Jul 2005 11:10:07 +1200, "Oleg Smolsky"
// This doesn't compile //std::for_each(v.begin(), v.end(), // boost::bind(&Handler::Test2, _1, _2, a, b));
This creates a functor with two arguments, _1 and _2, which calls Handler::Test2 with _1 as this, _2 as argument 1 of Test2, a as argument 2 of Test2 and b as argument 3 of Test2. But Test2 only has two arguments, and for_each only takes a functor with one argument. This is very confusing.... Let me paraphrase your explanation: I was trying to feed an extra argument to bind, which takes parameters in this fashion: boost::bind(function, this, arg1, arg2, arg3, etc)
Right?
Not exactly. Bind takes a variable number of arguments, so don't worry about that. Bind will create a functor which calls the function given as the first argument, with the arguments given in the rest of the call. So it's like: bind(function, value1, value2, value3, value4, ...) Which will generate a functor something like this: class anonymous_functor { public: void operator()() { function(value1, value2, value3, value4, ...); } }; If function is a member function, then bind obviously needs an object (of the correct type) for it to act on. The object (or 'this' pointer to it) is then the first argument of the bind expression. So it will look more like this: bind(&class::function, object, value1, value2, value3, ...) Generating: class anonymous_functor_for_member { public: void operator()() { object.function(value1, value2, value3, ...) } }; Note that neither of these functors take any arguments. This is because no placeholders were used in their bind expressions.
If yes, what's the exact meaning of _1, _2 placeholders? Also, how does that mash with functions vs methods?
If any of value1, value2, etc are a placeholder like _1, _2, etc, then the generated functor will have an argument corresponding to that placeholder. The simple case: bind(function, _1) Generates: class anonymous_one_arg_functor { public: void operator()(some_type arg1) { function(arg1) } }; The functor will have a number of arguments corresponding to the highest placeholder used. So if you can see an _2 in your expression, the functor will have two arguments; _even_ if you don't use _1. So: bind(function, _2, value1, value2, ...) Generates: class anonymous_two_arg_functor { public: void operator()(some_type arg1, some_other_type arg2) { function(arg2, value1, value2, ...) } }; Note that arg1 is passed to the functor but not used in the body, because you didn't use _1 in your bind expression. When you talk about member functions, it's all consistent with what I've previously said. The second argument to bind is the object, which can easily be a placeholder: bind(&class::function, _1, _2, value1, value2, ...) Generates: class anonymous_two_arg_functor_for_member { public: void operator()(class arg1, some_type arg2) { arg1.function(arg2, value1, value2, ...) } }; Does this make sense? Dave. -- Dave Slutzkin Melbourne, Australia daveslutzkin@fastmail.fm
On 7/28/05, Oleg Smolsky
Hi all,
I've just started using boost::bind and found the following problem:
class Handler { public: bool Test1(std::string sComponent); bool Test2(std::string sComponent, std::string sAddress); };
void Test() { std::vector<Handler> v;
// This compiles std::string a, b; std::for_each(v.begin(), v.end(), boost::bind(&Handler::Test1, _1, a));
// This doesn't compile //std::for_each(v.begin(), v.end(), // boost::bind(&Handler::Test2, _1, _2, a, b)); }
Environment: boost 1.32, VC8, WinXP.
Any ideas?
Thanks, Oleg.
Oleg - the _1 and _2 represent the parameter(s) passed *to* the boost::bind function by the caller (in this case std::for_each, which passes a Handler object instance). Now, std::for_each only passes one argument, so there can't be a _2 here. What you want for the second one is: boost::bind(&Handler::Test2, _1, a, b) The main thing to remember is that boost::bind makes explicit the implicit extra argument to object methods (the object instance, or 'this'). HTH Stuart Dootson
participants (3)
-
Dave Slutzkin
-
Oleg Smolsky
-
Stuart Dootson