bind, and member function with a parameter
I want to call a member function with a parameter from within an algorithm. http://boost.org/libs/bind/bind.html#with_algorithms gives an example: void animation::advance(int ms); std::vector<animation> anims; std::for_each(anims.begin(), anims.end(), boost::bind(&animation::advance, _1, ms)); I am using boost::lambda:: before _1. I get an error error C2825: 'F::result_type': cannot form a qualified name I am using MS VC7.1 and boost_1_33_1 Any ideas why this does not work? Thanks.
Alexander Shyrokov wrote:
I want to call a member function with a parameter from within an algorithm.
http://boost.org/libs/bind/bind.html#with_algorithms gives an example:
void animation::advance(int ms); std::vector<animation> anims; std::for_each(anims.begin(), anims.end(), boost::bind(&animation::advance, _1, ms));
I am using boost::lambda:: before _1. I get an error error C2825: 'F::result_type': cannot form a qualified name
I am using MS VC7.1 and boost_1_33_1
Any ideas why this does not work? Thanks.
In 1.33, you can't use boost::bind with Lambda's placeholders. Either use Bind's ::_1 placeholder, or use boost::lambda::bind. In 1.35, the code will work even with Lambda's placeholder.
"Peter Dimov" <pdimov@mmltd.net> wrote
In 1.33, you can't use boost::bind with Lambda's placeholders. Either use Bind's ::_1 placeholder, or use boost::lambda::bind.
In 1.35, the code will work even with Lambda's placeholder.
Is 1.35 correct or did you mean 1.34? Just an idea -- is it possible to have one universal set of placeholders in boost? Bind, Lambda, MPL, and possibly other libraries could then use some sort of redirection to their specialized placeholders... Might help to avoid some confusion. Regards, Arkadiy
Arkadiy Vertleyb wrote:
"Peter Dimov" <pdimov@mmltd.net> wrote
In 1.33, you can't use boost::bind with Lambda's placeholders. Either use Bind's ::_1 placeholder, or use boost::lambda::bind.
In 1.35, the code will work even with Lambda's placeholder.
Is 1.35 correct or did you mean 1.34?
1.35 is correct. 1.34 has been closed for new features for quite a while.
Just an idea -- is it possible to have one universal set of placeholders in boost? Bind, Lambda, MPL, and possibly other libraries could then use some sort of redirection to their specialized placeholders... Might help to avoid some confusion.
This isn't possible in general, but in 1.35 boost::bind implements the TR1 is_placeholder extension mechanism that allows anybody to define their own placeholders. I've already made Lambda's placeholders compatible with boost::bind. Bind's placeholders can't be made compatible with Lambda, since the latter places more requirements on its placeholders; they are fully-featured lambda expressions.
"Peter Dimov" <pdimov@mmltd.net> wrote
Just an idea -- is it possible to have one universal set of placeholders in boost? Bind, Lambda, MPL, and possibly other libraries could then use some sort of redirection to their specialized placeholders... Might help to avoid some confusion.
This isn't possible in general
Not sure I understand why... AFAIU, placeholders are either types (MPL), in which case some sort of traits can be used to redirect from, say, boost::_1 to mpl::_1, or const objects (Bind, Lambda), in which case some extra indirection through overload could possibly do the trick something like: template<class T> T redirect(const T&); template<int n> bind::arg<n> redirect(const boost::arg<n>&); Regards, Arkadiy
Thanks Peter, But how exactly do I specify _1? I have the same error if I do not specify any name space (as it is shown in the example) boost::_1 is not defined boost::bind::_1 generates "fatal error C1001: INTERNAL COMPILER ERROR" I do not know which error I like the best :) This is the code: #include <vector> #include <algorithm> #include <boost/bind.hpp> int main(int argc, char **argv) { typedef std::vector<std::vector<bool> > T2Dimensional; T2Dimensional vec; std::for_each(vec.begin(),vec.end() ,boost::bind(&std::vector<bool>::resize,_1,10)); return 0; } Thanks. Peter Dimov wrote:
Alexander Shyrokov wrote:
I want to call a member function with a parameter from within an algorithm.
http://boost.org/libs/bind/bind.html#with_algorithms gives an example:
void animation::advance(int ms); std::vector<animation> anims; std::for_each(anims.begin(), anims.end(), boost::bind(&animation::advance, _1, ms));
I am using boost::lambda:: before _1. I get an error error C2825: 'F::result_type': cannot form a qualified name
I am using MS VC7.1 and boost_1_33_1
Any ideas why this does not work? Thanks.
In 1.33, you can't use boost::bind with Lambda's placeholders. Either use Bind's ::_1 placeholder, or use boost::lambda::bind.
In 1.35, the code will work even with Lambda's placeholder.
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- Regards, Alexander. http://sjcomp.com
Alexander Shyrokov wrote:
Thanks Peter,
But how exactly do I specify _1? I have the same error if I do not specify any name space (as it is shown in the example)
boost::_1 is not defined boost::bind::_1 generates "fatal error C1001: INTERNAL COMPILER ERROR"
I do not know which error I like the best :)
This is the code:
#include <vector> #include <algorithm> #include <boost/bind.hpp>
int main(int argc, char **argv) { typedef std::vector<std::vector<bool> > T2Dimensional; T2Dimensional vec; std::for_each(vec.begin(),vec.end() ,boost::bind(&std::vector<bool>::resize,_1,10)); return 0; }
Your code is fine, sort of. The problem is that vector<>::resize takes two arguments. The second one has a default, but this information is lost when the pointer to member &std::vector<bool>::resize is taken. So you have to pass a value for it. std::for_each(vec.begin(),vec.end() ,boost::bind( &std::vector<bool>::resize, _1, 10, false ) );
Thanks! That solved the problem. Thanks a lot. Peter Dimov wrote:
#include <vector> #include <algorithm> #include <boost/bind.hpp>
int main(int argc, char **argv) { typedef std::vector<std::vector<bool> > T2Dimensional; T2Dimensional vec; std::for_each(vec.begin(),vec.end() ,boost::bind(&std::vector<bool>::resize,_1,10)); return 0; }
Your code is fine, sort of. The problem is that vector<>::resize takes two arguments. The second one has a default, but this information is lost when the pointer to member &std::vector<bool>::resize is taken. So you have to pass a value for it.
std::for_each(vec.begin(),vec.end() ,boost::bind( &std::vector<bool>::resize, _1, 10, false ) ); -- Regards, Alexander. http://sjcomp.com
"Peter Dimov" <pdimov@mmltd.net> writes:
Your code is fine, sort of. The problem is that vector<>::resize takes two arguments. The second one has a default, but this information is lost when the pointer to member &std::vector<bool>::resize is taken. So you have to pass a value for it.
std::for_each(vec.begin(),vec.end() ,boost::bind( &std::vector<bool>::resize, _1, 10, false ) );
And then there's the minor detail that you're not allowed to take the address of standard library (member) functions... to be technically portable and correct, you need to write a wrapper, e.g. struct resize_vector_bool { template <class V, class N> void operator()(V& v, N n) const { v.resize(n); } }; and then you can go back to using two arguments: std::for_each( vec.begin(), vec.end() , boost::bind( resize_vector_bool(), _1, 10)); [unless we repealed that restriction in the committee while I wasn't looking] -- Dave Abrahams Boost Consulting www.boost-consulting.com
David Abrahams <dave <at> boost-consulting.com> writes:
And then there's the minor detail that you're not allowed to take the address of standard library (member) functions... to be technically portable and correct, you need to write a wrapper, e.g.
struct resize_vector_bool { template <class V, class N> void operator()(V& v, N n) const { v.resize(n); } };
and then you can go back to using two arguments:
std::for_each( vec.begin(), vec.end() , boost::bind( resize_vector_bool(), _1, 10));
If I do it the correct way I get: boost_1_33_1\boost\bind.hpp(63) : error C2039: 'result_type' : is not a member of 'Geometry::resize_vector_bool' I've tried to convert it into a function, but it did not help. Why does that happen? Thanks.
David Abrahams <dave <at> boost-consulting.com> writes:
And then there's the minor detail that you're not allowed to take the address of standard library (member) functions... to be technically portable and correct, you need to write a wrapper, e.g.
If I do it the correct way I get: boost_1_33_1\boost\bind.hpp(63) : error C2039: 'result_type' : is not a member of 'Geometry::resize_vector_bool' Why does that happen?
struct resize_vector_bool
Should'nt that be struct resize_vector_bool : public std::binary_function<V,N,void> ? Regards Hendrik
struct resize_vector_bool
Should'nt that be
struct resize_vector_bool : public std::binary_function<V,N,void> ?
Thanks Hendrik, it solved the problem though I had to define template parameters. This is the final working version: template <class V, class N> struct resize_vector_bool : public std::binary_function<V,N,void> { void operator()(V& v, N n) const { v.resize(n); } }; std::vector<std::vector<bool> > vec; std::for_each( vec.begin(), vec.end() , boost::bind( resize_vector_bool<std::vector<bool>,int>(), _1, 10)); -- Regards, Alexander. http://sjcomp.com
Alexander Shyrokov wrote:
struct resize_vector_bool
Should'nt that be
struct resize_vector_bool : public std::binary_function<V,N,void> ?
Thanks Hendrik, it solved the problem though I had to define template parameters. This is the final working version:
template <class V, class N> struct resize_vector_bool : public std::binary_function<V,N,void> { void operator()(V& v, N n) const { v.resize(n); } };
If you want to go this way (there's nothing wrong in practice with using &vector<>::resize IMO), you only need to either: 1. Define result_type: struct resize_vector_bool { typedef void result_type; void operator()(V& v, N n) const { v.resize(n); } }; or 2. Supply it at the bind call by using bind<void>( ... ). This approach avoids having to specify V and N at the bind call.
participants (5)
-
Alexander Shyrokov
-
Arkadiy Vertleyb
-
David Abrahams
-
Hendrik Belitz
-
Peter Dimov