[bind] [lambda] making lambda::bind work
Hello, I've got some code that works ok with boost::bind and I'm trying to make it work with lambda::bind but am getting compilation errors. Why not leave it as-is? Just above the problem area of code I have another lambda expression and because I've already introduced lambda's _1 placeholder into the current scope and didn't want ambiguities arising so want to convert it over. I'm using VC++ 7.1 (2003) and Boost 1.35.0. I've created a stripped down test program to show the compilation problem: #include <algorithm> #include <memory> #include <string> #include <vector> #include <boost/bind.hpp> #include <boost/utility.hpp> #include <boost/lambda/bind.hpp> #include <boost/lambda/lambda.hpp> class GridItem : boost::noncopyable { public: bool AddOption(const char* item,bool unique = true) { // implementation code omitted! return true; } }; void GoodOldBoostBind() { std::auto_ptr<GridItem> item(new GridItem()); std::vector<std::string> options; std::for_each(options.begin(),options.end(), boost::bind(GridItem::AddOption,boost::ref(item),boost::bind(std::string::c_str,_1),true)); } void LambdaBind() { std::auto_ptr<GridItem> item(new GridItem()); std::vector<std::string> options; using namespace boost::lambda; using boost::lambda::_1; std::for_each(options.begin(),options.end(), bind(GridItem::AddOption,boost::ref(item),bind(std::string::c_str,_1),true)); // COMPILE ERROR ON ABOVE } int main() { } The error is: c:\releases\lib\boost\boost_1_35_0\include\boost\bind.hpp(338) : error C2664: 'R boost::_mfi::mf2<R,T,A1,A2>::operator ()<std::auto_ptr<_Ty>>(const U &,A1,A2) const' : cannot convert parameter 2 from 'boost::lambda::lambda_functor<T>' to 'const char *' with [ R=bool, T=GridItem, A1=const char *, A2=bool, _Ty=GridItem, U=std::auto_ptr<GridItem> ] and [ T=boost::lambda::lambda_functor_base<boost::lambda::action<2,boost::lambda::function_action<2>>,boost::tuples::tuple<const boost::lambda::detail::bind_traits<const char *(__thiscall std::basic_string<char,std::char_traits<char>,std::allocator<char>>::* const )(void) const>::type,const boost::lambda::detail::bind_traits<const boost::lambda::placeholder1_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type>> ] No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called Can anyone help with this? Thanks, Pete
Peter Barker:
void LambdaBind() { std::auto_ptr<GridItem> item(new GridItem()); std::vector<std::string> options;
using namespace boost::lambda; using boost::lambda::_1; std::for_each(options.begin(),options.end(),
bind(GridItem::AddOption,boost::ref(item),bind(std::string::c_str,_1),true)); // COMPILE ERROR ON ABOVE }
int main() { }
The error is: c:\releases\lib\boost\boost_1_35_0\include\boost\bind.hpp(338) : error C2664: 'R boost::_mfi::mf2<R,T,A1,A2>::operator ()<std::auto_ptr<_Ty>>(const U &,A1,A2) const' : cannot convert parameter 2 from 'boost::lambda::lambda_functor<T>' to 'const char *'
Since you use an unqualified call to bind, argument-dependent lookup finds boost::bind and prefers it as a better match. Nasty. You need '&' in front of the member functions, by the way. Omitting it is a MSVC-ism.
--- On Mon, 1/9/08, Peter Dimov <pdimov@pdimov.com> wrote:
From: Peter Dimov <pdimov@pdimov.com> Subject: Re: [Boost-users] [bind] [lambda] making lambda::bind work To: boost-users@lists.boost.org Date: Monday, 1 September, 2008, 6:13 PM Peter Barker:
void LambdaBind() { std::auto_ptr<GridItem> item(new GridItem()); std::vector<std::string> options;
using namespace boost::lambda; using boost::lambda::_1; std::for_each(options.begin(),options.end(),
bind(GridItem::AddOption,boost::ref(item),bind(std::string::c_str,_1),true));
// COMPILE ERROR ON ABOVE }
int main() { }
The error is:
c:\releases\lib\boost\boost_1_35_0\include\boost\bind.hpp(338) : error
C2664: 'R boost::_mfi::mf2<R,T,A1,A2>::operator ()<std::auto_ptr<_Ty>>(const U &,A1,A2) const' : cannot convert parameter 2 from 'boost::lambda::lambda_functor<T>' to 'const char *'
Since you use an unqualified call to bind, argument-dependent lookup finds boost::bind and prefers it as a better match. Nasty.
Thank you! It took me a while to figure out which argument made the compiler choose boost::bind. It was boost::ref(). After replacing that with var() I still had a compiler error as lambda::bind doesn't seem to work out of the box with std::auto_ptr. The following compiled: void LambdaBind() { GridItem item; std::vector<std::string> options; using namespace boost::lambda; using boost::lambda::_1; std::for_each(options.begin(),options.end(), bind(&GridItem::AddOption,var(item),bind(&std::string::c_str,_1),true)); // NO COMPILE ERROR ON ABOVE :-) }
You need '&' in front of the member functions, by the way. Omitting it is a MSVC-ism.
Ahh - I'm glad to learn that. Many thanks for your help.
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
--- On Mon, 1/9/08, Peter Dimov <pdimov@pdimov.com> wrote:
From: Peter Dimov <pdimov@pdimov.com> Subject: Re: [Boost-users] [bind] [lambda] making lambda::bind work To: boost-users@lists.boost.org Date: Monday, 1 September, 2008, 6:13 PM Peter Barker:
void LambdaBind() { std::auto_ptr<GridItem> item(new GridItem()); std::vector<std::string> options;
using namespace boost::lambda; using boost::lambda::_1; std::for_each(options.begin(),options.end(),
bind(GridItem::AddOption,boost::ref(item),bind(std::string::c_str,_1),true));
// COMPILE ERROR ON ABOVE }
int main() { }
The error is:
c:\releases\lib\boost\boost_1_35_0\include\boost\bind.hpp(338) : error
C2664: 'R boost::_mfi::mf2<R,T,A1,A2>::operator ()<std::auto_ptr<_Ty>>(const U &,A1,A2) const' : cannot convert parameter 2 from 'boost::lambda::lambda_functor<T>' to 'const char *'
Since you use an unqualified call to bind, argument-dependent lookup finds boost::bind and prefers it as a better match. Nasty.
You need '&' in front of the member functions, by the way. Omitting it is a MSVC-ism.
As mentioned in my other e-mail, that worked. I now have a couple of follow-up question about std::auto_ptr in bind: In my program auto_ptr is being used in boost::bind via boost::ref and it works fine. Does this work by design, or coincidence? I couldn't see boost::reference_wrapper and boost::addressof handling std::auto_ptr specially.
Peter Barker:
In my program auto_ptr is being used in boost::bind via boost::ref and it works fine. Does this work by design, or coincidence? I couldn't see boost::reference_wrapper and boost::addressof handling std::auto_ptr specially.
It works by design. boost::mem_fn uses get_pointer, and get_pointer for auto_ptr returns .get(). For lambda::bind, you may want to try using *ll::var(p) instead; lambda::bind has no special support for smart pointers.
--- On Tue, 2/9/08, Peter Dimov <pdimov@pdimov.com> wrote:
From: Peter Dimov <pdimov@pdimov.com> Subject: Re: [Boost-users] [bind] [lambda] making lambda::bind work To: boost-users@lists.boost.org Date: Tuesday, 2 September, 2008, 12:31 PM Peter Barker:
In my program auto_ptr is being used in boost::bind via boost::ref and it works fine. Does this work by design, or coincidence? I couldn't see boost::reference_wrapper and boost::addressof handling std::auto_ptr specially.
It works by design. boost::mem_fn uses get_pointer, and get_pointer for auto_ptr returns .get().
For lambda::bind, you may want to try using *ll::var(p) instead; lambda::bind has no special support for smart pointers.
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
I'll take a look at boost::mem_fn and get_pointer. You've also just saved me from posting up a question about lambda::bind and smart pointers. Really appreciate your help and thanks for boost::bind()!
Peter Dimov wrote in message news:004301c90cef$94246520$6507a80a@pdimov2...
It works by design. boost::mem_fn uses get_pointer, and get_pointer for auto_ptr returns .get().
Why there is get_pointer function ? As far as I can see, the same could be done with combination of operator * and operator .* , this would work for most smart-pointers without need to have get_pointer function.
Alexander:
Peter Dimov wrote in message news:004301c90cef$94246520$6507a80a@pdimov2...
It works by design. boost::mem_fn uses get_pointer, and get_pointer for auto_ptr returns .get().
Why there is get_pointer function ? As far as I can see, the same could be done with combination of operator * and operator .* , this would work for most smart-pointers without need to have get_pointer function.
Historical reasons. This is how boost::mem_fn was implemented and documented when it was first submitted for a Boost review, and nobody suggested using op* then. std::mem_fn is specified to use op*.
Peter Dimov wrote in message news:005a01c90dca$cc72cbc0$6507a80a@pdimov2...
As far as I can see, the same could be done with combination of operator * and operator .* , this would work for most smart-pointers without need to have get_pointer function.
Historical reasons. This is how boost::mem_fn was implemented and documented when it was first submitted for a Boost review, and nobody suggested using op* then. std::mem_fn is specified to use op*.
Ok, but what could be broken if mem_fn changed to .* now ?
participants (4)
-
Alexander
-
Alexander Gutenev
-
Peter Barker
-
Peter Dimov