member data pointer and nested bind

Hello, I've been trying to use STL alogorithms on POD struct data member without writing any user defined functor nor adding get/set member function to the POD sturct, instead I just wanted to use boost::mem_fn, boost::bind, boost::lambda for member data pointer. It was fine to use the member data pointer with any of boost::mem_fn, boost::bind and boost::lambda only until I tried to use them in the nested bind as an argument of outter bind. If I use them in nested bind, I got compile error message of "cannot convert parameter 1 from 'boost::_bi::bind_t<R,F,L> ' to 'const RECT *'" or "cannot convert parameter 1 from 'boost::lambda::lambda_functor<T>' to 'const RECT *'" As a boost newbie, it is too difficult for me to figure out the problem here. Maybe someone can help me out to sovle the problem. Thanks, Jae. The below is my test code. (BTW, I compiled it on VC71) ~~~ #include "stdafx.h" #include <wtypes.h> #include <vector> #include <algorithm> using std::vector; using std::find_if; #define BOOST_BIND_ENABLE_STDCALL #include <boost/bind.hpp> #include <boost/lambda/lambda.hpp> using boost::mem_fn; using boost::bind; // an arbitrary POD struct struct CTestClass { RECT rc; }; int main(int argc, char* argv[]) { vector<CTestClass> vecTestClass; CTestClass testObj = { { 0, 0, 100, 100} }; vecTestClass.push_back(testObj); ::OffsetRect(&testObj.rc, 100, 100); vecTestClass.push_back(testObj); LONG rc_left = mem_fn(&CTestClass::rc)(testObj).left; // mem_data_ptr & boost::mem_fn LONG rc_top = bind(&CTestClass::rc, _1)(testObj).top; // mem_data_ptr & boost::bind LONG rc_right = ((&boost::lambda::_1)->*&CTestClass::rc)(testObj).right; // mem_data_ptr & boost::lambda POINT ptTest = { 150, 150 }; ::PtInRect(&mem_fn(&CTestClass::rc)(testObj), ptTest); // ok ::PtInRect(&bind(&CTestClass::rc, _1)(testObj), ptTest); // ok ::PtInRect(&((&boost::lambda::_1)->*&CTestClass::rc)(testObj), ptTest); // ok vector<CTestClass>::iterator it_f1 = find_if(vecTestClass.begin(), vecTestClass.end(), bind(::PtInRect, &bind(&CTestClass::rc, _1), ptTest) ); // compile error! vector<CTestClass>::iterator it_f2 = find_if(vecTestClass.begin(), vecTestClass.end(), bind(::PtInRect, &((&boost::lambda::_1)->*&CTestClass::rc), ptTest) ); // compile error! return 0; } ~~~

JaeWook Choi wrote:
vector<CTestClass>::iterator it_f1 = find_if(vecTestClass.begin(), vecTestClass.end(), bind(::PtInRect, &bind(&CTestClass::rc, _1), ptTest) ); // compile error!
You can't use &bind with boost::bind, only with boost::lambda::bind. If you want to keep using boost::bind: template<class T> struct address_of { typedef T* result_type; result_type operator()( T & t ) const { return &t; } }; vector<CTestClass>::iterator it_f1 = find_if(vecTestClass.begin(), vecTestClass.end(), bind( ::PtInRect, bind( address_of<RECT>(), bind(&CTestClass::rc, _1) ), ptTest ) ); If you switch to lambda::bind you might have problems with the __stdcall convention that PtInRect uses; bind<BOOL>( ::PtInRect, ... ) might get you around that.

Hello Peter, Thank you so much. It seems both solutions are working well. BTW, Is there any links that explain the differences /or commons between boost::bind & boost::lambda::bind in their usage? It isn't quite easy for a newbie to look through boost source code to figure all that. Thanks again. Jae. ----- Original Message ----- From: "Peter Dimov" <pdimov@mmltd.net> Newsgroups: gmane.comp.lib.boost.user Sent: Sunday, February 19, 2006 8:23 AM Subject: Re: member data pointer and nested bind
JaeWook Choi wrote:
vector<CTestClass>::iterator it_f1 = find_if(vecTestClass.begin(), vecTestClass.end(), bind(::PtInRect, &bind(&CTestClass::rc, _1), ptTest) ); // compile error!
You can't use &bind with boost::bind, only with boost::lambda::bind. If you want to keep using boost::bind:
template<class T> struct address_of { typedef T* result_type; result_type operator()( T & t ) const { return &t; } };
vector<CTestClass>::iterator it_f1 = find_if(vecTestClass.begin(), vecTestClass.end(), bind( ::PtInRect, bind( address_of<RECT>(), bind(&CTestClass::rc, _1) ), ptTest ) );
If you switch to lambda::bind you might have problems with the __stdcall convention that PtInRect uses; bind<BOOL>( ::PtInRect, ... ) might get you around that.

JaeWook Choi wrote:
Hello Peter,
Thank you so much. It seems both solutions are working well. BTW, Is there any links that explain the differences /or commons between boost::bind & boost::lambda::bind in their usage?
There is http://www.boost.org/doc/html/lambda/s08.html#id2713474 but it doesn't seem to address neither of the questions you raised in your previous post. It should be possible to deduce most of the differences between lambda::bind and boost::bind by reading the documentation of the two libraries. For example, & doesn't work with boost::bind because boost::bind is not a "lambda" library and doesn't support operators (except for a very limited subset: http://www.boost.org/libs/bind/bind.html#operators that is a recent addition.) Lambda, on the other hand, doesn't support the boost::bind macro BOOST_BIND_ENABLE_STDCALL, however if you read http://www.boost.org/libs/bind/bind.html#Q_win32_api you'll see that it suggests an alternative of using bind<R>(...), so it makes sense to try it with lambda::bind and see whether it works. :-) Ideally, lambda::bind would be a superset of boost::bind, but for various reasons this is not the case today; at some point we probably need to accept this sad fact and write a page that lists all differences between the two.

Hello Peter, Thank you so much. It seems both solutions are working well. BTW, Is there any links that explain the differences /or commons between boost::bind & boost::lambda::bind in their usage? It isn't quite easy for a newbie to look through boost source code to figure all that. Thanks again. Jae. ----- Original Message ----- From: "Peter Dimov" <pdimov@mmltd.net> Newsgroups: gmane.comp.lib.boost.user Sent: Sunday, February 19, 2006 8:23 AM Subject: Re: member data pointer and nested bind
JaeWook Choi wrote:
vector<CTestClass>::iterator it_f1 = find_if(vecTestClass.begin(), vecTestClass.end(), bind(::PtInRect, &bind(&CTestClass::rc, _1), ptTest) ); // compile error!
You can't use &bind with boost::bind, only with boost::lambda::bind. If you want to keep using boost::bind:
template<class T> struct address_of { typedef T* result_type; result_type operator()( T & t ) const { return &t; } };
vector<CTestClass>::iterator it_f1 = find_if(vecTestClass.begin(), vecTestClass.end(), bind( ::PtInRect, bind( address_of<RECT>(), bind(&CTestClass::rc, _1) ), ptTest ) );
If you switch to lambda::bind you might have problems with the __stdcall convention that PtInRect uses; bind<BOOL>( ::PtInRect, ... ) might get you around that.

Hello Peter, Thank you so much. It seems both solutions are working well. BTW, Is there any links that explain the differences /or commons between boost::bind & boost::lambda::bind in their usage? It isn't quite easy for a newbie to look through boost source code to figure all that. Thanks again. Jae. "Peter Dimov" <pdimov@mmltd.net> wrote in message news:004d01c63557$b2b9dd70$6407a8c0@pdimov2...
JaeWook Choi wrote:
vector<CTestClass>::iterator it_f1 = find_if(vecTestClass.begin(), vecTestClass.end(), bind(::PtInRect, &bind(&CTestClass::rc, _1), ptTest) ); // compile error!
You can't use &bind with boost::bind, only with boost::lambda::bind. If you want to keep using boost::bind:
template<class T> struct address_of { typedef T* result_type; result_type operator()( T & t ) const { return &t; } };
vector<CTestClass>::iterator it_f1 = find_if(vecTestClass.begin(), vecTestClass.end(), bind( ::PtInRect, bind( address_of<RECT>(), bind(&CTestClass::rc, _1) ), ptTest ) );
If you switch to lambda::bind you might have problems with the __stdcall convention that PtInRect uses; bind<BOOL>( ::PtInRect, ... ) might get you around that.
participants (2)
-
JaeWook Choi
-
Peter Dimov