C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Lambda expression question

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
J Lindrud
Guest





PostPosted: Sun Aug 29, 2004 10:46 pm    Post subject: Lambda expression question Reply with 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?

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





PostPosted: Mon Aug 30, 2004 10:55 am    Post subject: Re: Lambda expression question Reply with quote



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)Surpriseds(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





PostPosted: Mon Aug 30, 2004 11:45 pm    Post subject: Re: Lambda expression question Reply with quote



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





PostPosted: Tue Aug 31, 2004 10:11 am    Post subject: Re: Lambda expression question Reply with quote

[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





PostPosted: Tue Aug 31, 2004 7:52 pm    Post subject: Re: Lambda expression question Reply with quote

[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





PostPosted: Wed Sep 01, 2004 9:58 am    Post subject: Re: Lambda expression question Reply with quote

[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





PostPosted: Wed Sep 01, 2004 9:24 pm    Post subject: Re: Lambda expression question Reply with quote

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





PostPosted: Thu Sep 02, 2004 11:54 am    Post subject: Re: Lambda expression question Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.