[bind] How do I....?

Use bind to call a free function on a vector of shared_ptrs? struct A { }; void f(const A&); std::vector<boost::shared_ptr<A> > v; for_each(v.begin(), v.end(), boost::bind(f, ???? ) ); what goes where ???? is? Thanks, Rob.

On Tue, Aug 18, 2009 at 10:07 AM, Robert Jones <robertgbjones@gmail.com>wrote:
Use bind to call a free function on a vector of shared_ptrs?
struct A { }; void f(const A&); std::vector<boost::shared_ptr<A> > v;
for_each(v.begin(), v.end(), boost::bind(f, ???? ) );
what goes where ???? is?
Two tactics spring to mind. One is to use boost::make_indirect_iterator on v.begin() and v.end() and just pass in f instead of the boost::bind(...). The other is to use RangeEx (shameless plug) thus: using namespace boost::adaptors; boost::for_each(v | indirected, f);
Thanks, Rob.
Regards, Neil Groves
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

On Tue, Aug 18, 2009 at 10:41 AM, Neil Groves <neil@grovescomputing.com>wrote:
On Tue, Aug 18, 2009 at 10:07 AM, Robert Jones <robertgbjones@gmail.com>wrote:
Use bind to call a free function on a vector of shared_ptrs?
struct A { }; void f(const A&); std::vector<boost::shared_ptr<A> > v;
for_each(v.begin(), v.end(), boost::bind(f, ???? ) );
what goes where ???? is?
Two tactics spring to mind.
One is to use boost::make_indirect_iterator on v.begin() and v.end() and just pass in f instead of the boost::bind(...).
Excellent - attack from the opposite direction, I'd not thought of that approach!
The other is to use RangeEx (shameless plug) thus:
using namespace boost::adaptors; boost::for_each(v | indirected, f);
Ah, if only I could! Doesn't that just demonstrate why RangeEx is so eagerly awaited. Thanks Neil - Rob.

Hello Neil,
Two tactics spring to mind.
One is to use boost::make_indirect_iterator on v.begin() and v.end() and just pass in f instead of the boost::bind(...).
Yes, this makes for quite readable code: for_each(make_indirect_iterator(vec.begin()), make_indirect_iterator(vec.end()), &foo);
The other is to use RangeEx (shameless plug) thus:
using namespace boost::adaptors; boost::for_each(v | indirected, f);
Creative! A good example of why it helps to have many power tools! Cheers, Bjorn Karlsson www.skeletonsoftware.net

Hello Rob,
Subject: [Boost-users] [bind] How do I....?
Use bind to call a free function on a vector of shared_ptrs?
struct A { }; void f(const A&); std::vector<boost::shared_ptr<A> > v;
for_each(v.begin(), v.end(), boost::bind(f, ???? ) );
what goes where ???? is?
You have two options if you want to use binders: 1) Use Boost.Bind with nested binds, binding operator* of shared_ptr in the inner bind. for_each(vec.begin(), vec.end(), boost::bind(&foo, boost::bind(&boost::shared_ptr<A>::operator*, _1))); 2) Use Boost.Lambda's bind() and dereference the placeholder directly in the bind expression. for_each(vec.begin(), vec.end(), bind(&foo, *_1)); Here's a complete example demonstrating option 2). #include <vector> #include <algorithm> #include "boost/shared_ptr.hpp" #include "boost/lambda/bind.hpp" #include "boost/lambda/lambda.hpp" class A {}; void foo(const A& a) {} int main(int argc, char** argv) { using boost::lambda::bind; using boost::lambda::_1; std::vector<boost::shared_ptr<A> > vec; vec.push_back(boost::shared_ptr<A>(new A())); for_each(vec.begin(), vec.end(), bind(&foo, *_1)); return 0; } Cheers, Bjorn Karlsson www.skeletonsoftware.net

2009/8/18 Björn Karlsson <Bjorn.Karlsson@readsoft.com>
Hello Rob,
Subject: [Boost-users] [bind] How do I....?
Use bind to call a free function on a vector of shared_ptrs?
struct A { }; void f(const A&); std::vector<boost::shared_ptr<A> > v;
for_each(v.begin(), v.end(), boost::bind(f, ???? ) );
what goes where ???? is?
You have two options if you want to use binders:
1) Use Boost.Bind with nested binds, binding operator* of shared_ptr in the inner bind.
for_each(vec.begin(), vec.end(), boost::bind(&foo, boost::bind(&boost::shared_ptr<A>::operator*, _1)));
This was about the best I could think of too, and is, I think, what I'll do.
2) Use Boost.Lambda's bind() and dereference the placeholder directly in the bind expression.
for_each(vec.begin(), vec.end(), bind(&foo, *_1));
Much as I like Lambda for virgin code, in my work code base there's a very visible inclusion of Boost.Bind, with placeholders in the global namespace. I've concluded that the pain of clashing placeholders just isn't worth it, so I steer clear of Lambda now. Thanks Bjorn. - Rob.

Robert Jones wrote:
2009/8/18 Björn Karlsson <Bjorn.Karlsson@readsoft.com <mailto:Bjorn.Karlsson@readsoft.com>>
2) Use Boost.Lambda's bind() and dereference the placeholder directly in the bind expression.
for_each(vec.begin(), vec.end(), bind(&foo, *_1));
Much as I like Lambda for virgin code, in my work code base there's a very visible inclusion of Boost.Bind, with placeholders in the global namespace. I've concluded that the pain of clashing placeholders just isn't worth it, so I steer clear of Lambda now.
Thanks Bjorn.
- Rob.
Rob - Let me suggest Boost.Phoenix. Phoenix is an amazingly powerful library that will handle all of your bind and lambda needs. You also wont suffer from the plagued global namespace fiasco by mixing Boost.Bind and Boost.Lambda. Your example with Phoenix: #include <vector> #include <algorithm> #include <boost/shared_ptr.hpp> #include <boost/spirit/home/phoenix/core.hpp> #include <boost/spirit/home/phoenix/operator.hpp> #include <boost/spirit/home/phoenix/bind/bind_function.hpp> struct A {}; void foo( const A& ) {} int main() { using namespace boost::phoenix; using namespace boost::phoenix::arg_names; std::vector< boost::shared_ptr< A > > vec; vec.push_back( boost::shared_ptr< A >( new A ) ); std::for_each( vec.begin(), vec.end(), bind( &foo, *arg1 ) ); return 0; } I hope this helps out. Best Regards - Michael -- ---------------------------------- Michael Caisse Object Modeling Designs www.objectmodelingdesigns.com

On Tue, Aug 18, 2009 at 11:10 AM, Michael Caisse<boost@objectmodelingdesigns.com> wrote:
Robert Jones wrote:
2009/8/18 Björn Karlsson <Bjorn.Karlsson@readsoft.com <mailto:Bjorn.Karlsson@readsoft.com>>
2) Use Boost.Lambda's bind() and dereference the placeholder directly in the bind expression.
for_each(vec.begin(), vec.end(), bind(&foo, *_1));
Much as I like Lambda for virgin code, in my work code base there's a very visible inclusion of Boost.Bind, with placeholders in the global namespace. I've concluded that the pain of clashing placeholders just isn't worth it, so I steer clear of Lambda now.
Thanks Bjorn.
- Rob.
Rob -
Let me suggest Boost.Phoenix. Phoenix is an amazingly powerful library that will handle all of your bind and lambda needs. You also wont suffer from the plagued global namespace fiasco by mixing Boost.Bind and Boost.Lambda.
Your example with Phoenix:
#include <vector> #include <algorithm> #include <boost/shared_ptr.hpp> #include <boost/spirit/home/phoenix/core.hpp> #include <boost/spirit/home/phoenix/operator.hpp> #include <boost/spirit/home/phoenix/bind/bind_function.hpp>
struct A {};
void foo( const A& ) {}
int main() { using namespace boost::phoenix; using namespace boost::phoenix::arg_names;
std::vector< boost::shared_ptr< A > > vec; vec.push_back( boost::shared_ptr< A >( new A ) );
std::for_each( vec.begin(), vec.end(), bind( &foo, *arg1 ) ); return 0; }
I hope this helps out.
This is another vote for Boost.Phoenix2, its bind replaces all possible uses I have ever seen of Boost.Bind or Boost.Lambda::bind and in an easier way.

On Tue, Aug 18, 2009 at 6:10 PM, Michael Caisse < boost@objectmodelingdesigns.com> wrote:
Robert Jones wrote:
2009/8/18 Björn Karlsson <Bjorn.Karlsson@readsoft.com <mailto: Bjorn.Karlsson@readsoft.com>>
2) Use Boost.Lambda's bind() and dereference the placeholder directly in the bind expression.
for_each(vec.begin(), vec.end(), bind(&foo, *_1));
Much as I like Lambda for virgin code, in my work code base there's a very visible inclusion of Boost.Bind, with placeholders in the global namespace. I've concluded that the pain of clashing placeholders just isn't worth it, so I steer clear of Lambda now.
Thanks Bjorn.
- Rob.
Rob -
Let me suggest Boost.Phoenix. Phoenix is an amazingly powerful library that will handle all of your bind and lambda needs. You also wont suffer from the plagued global namespace fiasco by mixing Boost.Bind and Boost.Lambda.
Ah, yes, Phoenix...... I'm never sure of the status of Phoenix - it's not listed as a first class library in the documentation, but buried inside the Spirit docs, and I understand that's about to change. So will all the #include paths change, or indeed some aspects of the functionality? Thanks Micheal - Rob.

On Tue, Aug 18, 2009 at 1:58 PM, Robert Jones<robertgbjones@gmail.com> wrote:
On Tue, Aug 18, 2009 at 6:10 PM, Michael Caisse <boost@objectmodelingdesigns.com> wrote:
Robert Jones wrote:
2009/8/18 Björn Karlsson <Bjorn.Karlsson@readsoft.com <mailto:Bjorn.Karlsson@readsoft.com>>
2) Use Boost.Lambda's bind() and dereference the placeholder directly in the bind expression.
for_each(vec.begin(), vec.end(), bind(&foo, *_1));
Much as I like Lambda for virgin code, in my work code base there's a very visible inclusion of Boost.Bind, with placeholders in the global namespace. I've concluded that the pain of clashing placeholders just isn't worth it, so I steer clear of Lambda now.
Thanks Bjorn.
- Rob.
Rob -
Let me suggest Boost.Phoenix. Phoenix is an amazingly powerful library that will handle all of your bind and lambda needs. You also wont suffer from the plagued global namespace fiasco by mixing Boost.Bind and Boost.Lambda.
Ah, yes, Phoenix......
I'm never sure of the status of Phoenix - it's not listed as a first class library in the documentation, but buried inside the Spirit docs, and I understand that's about to change. So will all the #include paths change, or indeed some aspects of the functionality?
It should not I would think. Phoenix2 (phoenix in spirit, the old phoenix is phoenix1, ignore it) is heavily used by the very latest Spirit2.1 codebase, and spirit tends to always include forwarding headers as things move around anyway.

Robert Jones wrote:
On Tue, Aug 18, 2009 at 6:10 PM, Michael Caisse <boost@objectmodelingdesigns.com <mailto:boost@objectmodelingdesigns.com>> wrote:
Let me suggest Boost.Phoenix. Phoenix is an amazingly powerful library that will handle all of your bind and lambda needs. You also wont suffer from the plagued global namespace fiasco by mixing Boost.Bind and Boost.Lambda.
Ah, yes, Phoenix......
I'm never sure of the status of Phoenix - it's not listed as a first class library in the documentation, but buried inside the Spirit docs, and I understand that's about to change. So will all the #include paths change, or indeed some aspects of the functionality?
Thanks Micheal
- Rob. Phoenix is an integral part of Spirit 2.1. While it is a "detail" of sorts you will notice in the libs/spirit directory that Phoenix has first class treatment. I suspect the best answers to your questions are in Hartmut's summary of the Phoenix review:
http://lists.boost.org/boost-announce/2008/10/0205.php Others may have better insider knowledge. I can attest to the quality of the library and docs as well as the stability. I started using the library because of Spirit 2.1; however, I now use it for all of my lambda/bind needs. Michael -- ---------------------------------- Michael Caisse Object Modeling Designs www.objectmodelingdesigns.com
participants (5)
-
Björn Karlsson
-
Michael Caisse
-
Neil Groves
-
OvermindDL1
-
Robert Jones