 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
J Lindrud Guest
|
Posted: Sun Aug 29, 2004 10:46 pm Post subject: Lambda expression question |
|
|
Hi all,
I have the following container
std::vector< boost::function funcs;
, containing function objects that are to be called with a
std::ostream argument. In order to iterate through the container and
make all the function calls, I can write:
for (unsigned int i=0; i
{
funcs[i]( std::cout );
}
However, I would rather use the more abstract form
std::for_each(
funcs.begin(),
funcs.end(),
???
);
where the ??? represents a boost::lambda expression, but I simply
can't figure out what the lambda expression should look like. Would
have liked to write _1( boost::ref(std::cout)), but that's a no-go.
Any suggestions?
Thanks!
Jarl.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Carl Barron Guest
|
Posted: Mon Aug 30, 2004 10:55 am Post subject: Re: Lambda expression question |
|
|
J Lindrud <jlindrud (AT) hotmail (DOT) com> wrote:
| Quote: | Hi all,
I have the following container
std::vector< boost::function funcs;
, containing function objects that are to be called with a
std::ostream argument. In order to iterate through the container and
make all the function calls, I can write:
for (unsigned int i=0; i<funcs.size(); i++)
{
funcs[i]( std::cout );
}
However, I would rather use the more abstract form
std::for_each(
funcs.begin(),
funcs.end(),
???
);
|
Use a functor at a namespace scope.
typedef boost::function
class DoIt
{
std::ostream &os;
public:
DoIt(std::ostream &a) s(a){}
void operator () (Function &f) {f(os);}
};
int main()
{
// ...
std::for_wach(funcs.begin(),funcs.end(),DoIt(std::cout));
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Maxim Yegorushkin Guest
|
Posted: Mon Aug 30, 2004 11:45 pm Post subject: Re: Lambda expression question |
|
|
Lindrud <jlindrud (AT) hotmail (DOT) com> wrote:
| Quote: | I have the following container
std::vector< boost::function funcs;
, containing function objects that are to be called with a
std::ostream argument. In order to iterate through the container and
make all the function calls, I can write:
for (unsigned int i=0; i<funcs.size(); i++)
{
funcs[i]( std::cout );
}
However, I would rather use the more abstract form
std::for_each(
funcs.begin(),
funcs.end(),
???
);
where the ??? represents a boost::lambda expression, but I simply
can't figure out what the lambda expression should look like. Would
have liked to write _1( boost::ref(std::cout)), but that's a no-go.
Any suggestions?
|
Unless there is a newer syntax for binding operator() in boost::lambda,
you may use something like this:
int main()
{
typedef boost::function
std::vector<fun_t> funcs;
std::for_each(
funcs.begin()
, funcs.end()
, boost::lambda::bind(&fun_t::operator(), boost::lambda::_1, boost::lambda::var(std::cout))
);
}
--
Maxim Yegorushkin
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
J Lindrud Guest
|
Posted: Tue Aug 31, 2004 10:11 am Post subject: Re: Lambda expression question |
|
|
[email]cbarron3 (AT) ix (DOT) netcom.com[/email] (Carl Barron) wrote in message news:<1gjarbs.oy6it4iyw66tN%cbarron3 (AT) ix (DOT) netcom.com>...
| Quote: |
Use a functor at a namespace scope.
|
Yeah, I know about functors, but if I have to write a whole new class
every time I want to use std::for_each, I'll probably just stick to
the plain old for loop.
Using lambda expressions makes std::for_each look a whole lot nicer, I
just didn't see how to make it work in this particular case.
/Jarl
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
David Abrahams Guest
|
Posted: Tue Aug 31, 2004 7:52 pm Post subject: Re: Lambda expression question |
|
|
[email]jlindrud (AT) hotmail (DOT) com[/email] (J Lindrud) writes:
| Quote: | Hi all,
I have the following container
std::vector< boost::function funcs;
, containing function objects that are to be called with a
std::ostream argument. In order to iterate through the container and
make all the function calls, I can write:
for (unsigned int i=0; i
{
funcs[i]( std::cout );
}
However, I would rather use the more abstract form
std::for_each(
funcs.begin(),
funcs.end(),
???
);
where the ??? represents a boost::lambda expression, but I simply
can't figure out what the lambda expression should look like. Would
have liked to write _1( boost::ref(std::cout)), but that's a no-go.
Any suggestions?
|
I'm not sure what the answer is, but you'll surely have better luck
posting on one of the appropriate Boost mailing lists
http://www.boost.org/more/mailing_lists.htm
I've asked the lambda library authors to try to follow up on this one.
HTH,
--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Terje Sletteb? Guest
|
Posted: Wed Sep 01, 2004 9:58 am Post subject: Re: Lambda expression question |
|
|
[email]jlindrud (AT) hotmail (DOT) com[/email] (J Lindrud) wrote in message news:<ff70dbdb.0408290540.25af91e8 (AT) posting (DOT) google.com>...
| Quote: | Hi all,
I have the following container
std::vector< boost::function funcs;
, containing function objects that are to be called with a
std::ostream argument. In order to iterate through the container and
make all the function calls, I can write:
for (unsigned int i=0; i<funcs.size(); i++)
{
funcs[i]( std::cout );
}
However, I would rather use the more abstract form
std::for_each(
funcs.begin(),
funcs.end(),
???
);
where the ??? represents a boost::lambda expression, but I simply
can't figure out what the lambda expression should look like. Would
have liked to write _1( boost::ref(std::cout)), but that's a no-go.
Any suggestions?
|
You can get there using Lambda's bind. Here's a complete, working
example for the above (tested on g++ 3.2):
--- Start ---
#include
#include <vector>
#include <algorithm>
#include <boost/function.hpp>
#include <boost/ref.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
using boost::lambda::_1;
void f(std::ostream &out)
{
out << "f()n";
}
typedef boost::function
int main()
{
std::vector<element_type> funcs;
funcs.push_back(element_type(f));
funcs.push_back(element_type(f));
funcs.push_back(element_type(f));
std::for_each(
funcs.begin(),
funcs.end(),
boost::lambda::bind<void>(_1,boost::ref(std::cout)));
}
--- End ---
This prints:
f()
f()
f()
Boost.Lambda needs an expression that can be turned into a function
object. Doing _1(...) will attempt to call the function call operator
on the _1 object, rather than on what _1 will be a placeholder for in
the expression.
Also, bind needs to be told the return type, void, as it can't deduce
it from the boost::function object (unlike a function). Try the
following substitutions in the above code, to see this:
typedef void(*element_type)(std::ostream &);
funcs.push_back(f);
funcs.push_back(f);
funcs.push_back(f);
boost::lambda::bind(_1,boost::ref(std::cout))); // No <void>
boost::function may, however, be adapted to work with Lambda's bind,
using something like this:
template<class Base,class R>
struct bind_adapter : Base
{
template<class P1>
bind_adapter(const P1 &p1) : Base(p1) {};
template<class Args>
struct sig { typedef R type; };
};
typedef bind_adapter<boost::function
element_type;
boost::lambda::bind(_1,boost::ref(std::cout))); // No <void> here,
either
Alternatively, if boost::function had a "sig" member template like the
above, it could be used as is. Perhaps a useful addition to
boost::function?
However, converging on the standard proposal result_of may be better
in the long run.
By the way, the above can also be done with Boost.Bind, with something
extra:
#include <boost/bind.hpp>
#include <boost/bind/apply.hpp>
boost::bind(boost::apply<void>(),_1,boost::ref(std::cout)));
Regards,
Terje
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
tom_usenet Guest
|
Posted: Wed Sep 01, 2004 9:24 pm Post subject: Re: Lambda expression question |
|
|
On 29 Aug 2004 18:46:27 -0400, [email]jlindrud (AT) hotmail (DOT) com[/email] (J Lindrud) wrote:
| Quote: | Hi all,
I have the following container
std::vector< boost::function funcs;
, containing function objects that are to be called with a
std::ostream argument. In order to iterate through the container and
make all the function calls, I can write:
for (unsigned int i=0; i<funcs.size(); i++)
{
funcs[i]( std::cout );
}
However, I would rather use the more abstract form
std::for_each(
funcs.begin(),
funcs.end(),
???
|
boost::lambda::bind
| Quote: | );
where the ??? represents a boost::lambda expression, but I simply
can't figure out what the lambda expression should look like. Would
have liked to write _1( boost::ref(std::cout)), but that's a no-go.
Any suggestions?
|
It seems that operator() hasn't been overloaded to support direct
calls; I imagine there were technical problems with supporting the
"obvious" syntax, which is why bind was supplied.
Tom
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
David Abrahams Guest
|
Posted: Thu Sep 02, 2004 11:54 am Post subject: Re: Lambda expression question |
|
|
tom_usenet <tom_usenet (AT) hotmail (DOT) com> writes:
| Quote: | On 29 Aug 2004 18:46:27 -0400, [email]jlindrud (AT) hotmail (DOT) com[/email] (J Lindrud) wrote:
Hi all,
I have the following container
std::vector< boost::function funcs;
, containing function objects that are to be called with a
std::ostream argument. In order to iterate through the container and
make all the function calls, I can write:
for (unsigned int i=0; i<funcs.size(); i++)
{
funcs[i]( std::cout );
}
However, I would rather use the more abstract form
std::for_each(
funcs.begin(),
funcs.end(),
???
boost::lambda::bind
);
where the ??? represents a boost::lambda expression, but I simply
can't figure out what the lambda expression should look like. Would
have liked to write _1( boost::ref(std::cout)), but that's a no-go.
Any suggestions?
It seems that operator() hasn't been overloaded to support direct
calls; I imagine there were technical problems with supporting the
"obvious" syntax,
|
Well, yeah. _1 is a lambda expression that returns its first
argument:
_1(44) == 44
If you look at http://tinyurl.com/5jpr4#sect:placeholders you'll see:
int i, j, k;
_1(i, j, k) // returns i, discards j and k
| Quote: | which is why bind was supplied.
|
I don't think so; bind has other uses. Check the docs:
--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|