std::find_if, boost::mem_fn and boost::not1
Hi All, I'm just getting into using boost and stl algorithms, and I'm getting some indecipherable compiler errors that I'd like some help understanding. Here's some sample code: <------------------------SNIP------------------------> #include <boost/shared_ptr.hpp> #include <boost/functional.hpp> #include <boost/bind.hpp> class CEgg { public: bool IsHatched() const; }; typedef std::vector< boost::shared_ptr<CEgg> > tEggsVector; //this function compiles with no problems bool SomeEggsHaveHatched() { tEggsVector basketOfEggs; tEggsVector::const_iterator it = std::find_if( basketOfEggs.begin(), basketOfEggs.end(), boost::mem_fn( &CEgg::IsHatched ) ); bool bSomeEggsHaveHatched = ( it != basketOfEggs.end() ); return bSomeEggsHaveHatched; } //this function doesn't compile, //presumably because of the boost::not1 usage bool AllEggsHaveHatched() { tEggsVector basketOfEggs; tEggsVector::iterator it = std::find_if( basketOfEggs.begin(), basketOfEggs.end(), boost::not1( boost::mem_fn( &CEgg::IsHatched ) ) ); bool bSomeEggsHaventHatched = ( it != basketOfEggs.end() ); return !bSomeEggsHaventHatched; } <------------------------SNIP------------------------> When I try and compile this in Visual C++ 2003 I get the following compile errors for AllEggsHaveHatched(): c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\algorithm(64) : error C2664: 'bool boost::unary_negate<Predicate>::operator ()(const boost::call_traits<T>::param_type) const' : cannot convert parameter 1 from 'std::allocator<_Ty>::value_type' to 'const boost::call_traits<T>::param_type' with [ Predicate=boost::_mfi::cmf0<bool,CEgg>, T=boost::unary_traits<boost::_mfi::cmf0<bool,CEgg>>::argument_type ] and [ _Ty=boost::shared_ptr<CEgg> ] and [ T=boost::unary_traits<boost::_mfi::cmf0<bool,CEgg>>::argument_type ] No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called c:\WORK\4DCapture_Soln\VideoCapture\PixelinkCaptureFacade.h(46) : see reference to function template instantiation '_InIt std::find_if<std::vector<_Ty>::iterator,boost::unary_negate<Predicate>>(_InIt,_InIt,_Pr)' being compiled with [ _InIt=std::vector<boost::shared_ptr<CEgg>>::iterator, _Ty=boost::shared_ptr<CEgg>, Predicate=boost::_mfi::cmf0<bool,CEgg>, _Pr=boost::unary_negate<boost::_mfi::cmf0<bool,CEgg>> ] Any idea why boost::not1 seems to be causing problems? Should I be using std::not1? or boost::mem_fun instead of boost:mem_fn? Cheers and TIA, Pete
Pete Hodgson wrote:
Hi All,
I'm just getting into using boost and stl algorithms, and I'm getting some indecipherable compiler errors that I'd like some help understanding.
Here's some sample code:
[...]
typedef std::vector< boost::shared_ptr<CEgg> > tEggsVector;
//this function doesn't compile, //presumably because of the boost::not1 usage bool AllEggsHaveHatched() { tEggsVector basketOfEggs;
tEggsVector::iterator it = std::find_if( basketOfEggs.begin(), basketOfEggs.end(), boost::not1( boost::mem_fn( &CEgg::IsHatched ) ) );
not1 doesn't work well with boost::mem_fn applied to shared_ptr, but you may try !boost::bind( &CEgg::IsHatched, _1 ) instead.
Peter Dimov wrote: ...
not1 doesn't work well with boost::mem_fn applied to shared_ptr, but you may try
!boost::bind( &CEgg::IsHatched, _1 )
instead.
I tried the following: bool SomeEggsHaveHatched() { tEggsVector basketOfEggs; using boost::lambda::_1; tEggsVector::const_iterator it = std::find_if( basketOfEggs.begin(), basketOfEggs.end(), boost::bind( &CEgg::IsHatched, _1 ) ); bool bSomeEggsHaveHatched = ( it != basketOfEggs.end() ); return bSomeEggsHaveHatched; } but it won't compile, giving: <------------------------------SNIP---------------------------------------> c:\WORK\4DCapture_Soln\thirdparty\boost\boost\bind\mem_fn_template.hpp(90) : error C2664: 'R boost::_mfi::cmf0<R,T>::call<const U>(const U &,const T *) const' : cannot convert parameter 2 from 'const boost::lambda::lambda_functor<T>' to 'const CEgg *' with [ R=bool, T=CEgg, U=boost::lambda::placeholder1_type ] and [ T=boost::lambda::lambda_functor_base<boost::lambda::other_action<boost::lambda::addressof_action>,boost::tuples::tuple<boost::lambda::lambda_functor<boost::lambda::placeholder<1>>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>> ] No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called c:\WORK\4DCapture_Soln\thirdparty\boost\boost\bind.hpp(193) : see reference to function template instantiation 'R boost::_mfi::cmf0<R,T>::operator ()<boost::lambda::lambda_functor<boost::lambda::placeholder<1>>>(const U &) const' being compiled with [ R=bool, T=CEgg, U=boost::lambda::placeholder1_type ] c:\WORK\4DCapture_Soln\thirdparty\boost\boost\bind\bind_template.hpp(33) : see reference to function template instantiation 'R boost::_bi::list1<A1>::operator ()<boost::_bi::bind_t<R,F,L>::result_type,F,boost::_bi::list1<boost::shared_ptr<T> &>>(boost::_bi::type<boost::_bi::bind_t<R,F,L>::result_type>,F,A &)' being compiled with [ R=boost::_bi::bind_t<bool,boost::_mfi::cmf0<bool,CEgg>,boost::_bi::list1<boost::_bi::list_av_1<boost::lambda::placeholder1_type>::B1>>::result_type, A1=boost::_bi::list_av_1<boost::lambda::placeholder1_type>::B1, F=boost::_mfi::cmf0<bool,CEgg>, L=boost::_bi::list1<boost::_bi::list_av_1<boost::lambda::placeholder1_type>::B1>, T=CEgg, A=boost::_bi::list1<std::allocator<boost::shared_ptr<CEgg>>::value_type &> ] c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\algorithm(64) : see reference to function template instantiation 'boost::_bi::bind_t<R,F,L>::result_type boost::_bi::bind_t<R,F,L>::operator ()<std::allocator<_Ty>::value_type>(A1 &)' being compiled with [ R=bool, F=boost::_mfi::cmf0<bool,CEgg>, L=boost::_bi::list1<boost::_bi::list_av_1<boost::lambda::placeholder1_type>::B1>, _Ty=boost::shared_ptr<CEgg>, A1=std::allocator<boost::shared_ptr<CEgg>>::value_type ] c:\WORK\4DCapture_Soln\VideoCapture\PixelinkCaptureFacade.h(34) : see reference to function template instantiation '_InIt std::f ind_if<std::vector<_Ty>::iterator,boost::_bi::bind_t<R,F,L>>(_InIt,_InIt,_Pr)' being compiled with [ _InIt=std::vector<boost::shared_ptr<CEgg>>::iterator, _Ty=boost::shared_ptr<CEgg>, R=bool, F=boost::_mfi::cmf0<bool,CEgg>, L=boost::_bi::list1<boost::_bi::list_av_1<boost::lambda::placeholder1_type>::B1>, _Pr=boost::_bi::bind_t<bool,boost::_mfi::cmf0<bool,CEgg>,boost::_bi::list1<boost::_bi::list_av_1<boost::lambda::placeholder1_type>::B1>> ] <------------------------------SNIP---------------------------------------> Any clues as to what's going on here?
Pete Hodgson wrote:
Peter Dimov wrote: ...
not1 doesn't work well with boost::mem_fn applied to shared_ptr, but you may try
!boost::bind( &CEgg::IsHatched, _1 )
instead.
I tried the following:
bool SomeEggsHaveHatched() { tEggsVector basketOfEggs;
using boost::lambda::_1;
tEggsVector::const_iterator it = std::find_if( basketOfEggs.begin(), basketOfEggs.end(), boost::bind( &CEgg::IsHatched, _1 ) );
bool bSomeEggsHaveHatched = ( it != basketOfEggs.end() ); return bSomeEggsHaveHatched; }
but it won't compile, giving:
[...]
Any clues as to what's going on here?
You are using boost::bind with boost::lambda::_1. Remove the using boost::lambda::_1 line.
Pete Hodgson wrote:
using boost::lambda::_1;
tEggsVector::const_iterator it = std::find_if( basketOfEggs.begin(), basketOfEggs.end(), boost::bind( &CEgg::IsHatched, _1 ) );
You're using lambda placeholders for the bind library binders. You need to use the bind library placeholders or the lambda library binders. In other words, you must not mix the two. It's rather unpleasant, but at the moment they are not compatible. Sebastian Redl
Sebastian Redl wrote:
Pete Hodgson wrote:
using boost::lambda::_1;
tEggsVector::const_iterator it = std::find_if( basketOfEggs.begin(), basketOfEggs.end(), boost::bind( &CEgg::IsHatched, _1 ) );
You're using lambda placeholders for the bind library binders. You need to use the bind library placeholders or the lambda library binders. In other words, you must not mix the two. It's rather unpleasant, but at the moment they are not compatible.
Sebastian Redl
Ah, I didn't realize that there were two different _1 implementations. Thanks for the help guys.
participants (3)
-
Pete Hodgson
-
Peter Dimov
-
Sebastian Redl