Thanks, Rob.
_______________________________________________
Boost-users mailing list
Boost...@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users
> Subject: [Boost-users] [bind] How do I....?
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
On Tue, Aug 18, 2009 at 10:07 AM, Robert Jones <robert...@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);
> 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....?
You have two options if you want to use binders:>
> 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?
>
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));
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
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.
Robert Jones wrote:
2009/8/18 Björn Karlsson <Bjorn.K...@readsoft.com <mailto:Bjorn.K...@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.
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.
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.