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 

Simple lambda expressions (gcc only)

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





PostPosted: Tue Aug 29, 2006 8:24 pm    Post subject: Simple lambda expressions (gcc only) Reply with quote



Below is an example of some simple lambda expressions (but no
closures) using gcc's feature of brace-enclosed compound statements
inside of parentheses. The advantage over Boost.Lambda is that you can
write a full block of code and the arguments (_1, _2 etc.) are the
same as the lambda function arguments. The disadvantage is that it
doesn't allow closures (probably using functors instead of functions
but I haven't tried it yet).

Would braces inside parentheses be allowed by any future C++ standard?

Thanks.


#include <iostream>
#include <vector>

using namespace std;

#define lambda1(out_type, in_type, body) \
({ \
struct local_ { \
static out_type local_fn_(in_type _1) \
{ \
body; \
} \
}; \
&local_::local_fn_; \
})

int main()
{
vector<unsigned int> v;
v.push_back(0);
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);

// increment the vector elements
for_each(v.begin(), v.end(), lambda1(void, unsigned int&, ++_1));

// print the vector elements
for_each(v.begin(), v.end(),
lambda1(void, unsigned int, cout << _1 << endl));

// print the factorial of each element in the vector
for_each(v.begin(), v.end(),
lambda1(void, unsigned int,
cout << "factorial(" << _1 << ") = "
<< lambda1(unsigned int, unsigned int,
unsigned int fact = 1;
for (unsigned int i = 2; i <= _1; ++i)
{
fact *= i;
}
return fact)(_1)
<< endl));

return 0;
}

--
Catalin

{ bogus confidentiality notice removed. -mod }

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Lucian Radu Teodorescu
Guest





PostPosted: Wed Aug 30, 2006 5:18 pm    Post subject: Re: Simple lambda expressions (gcc only) Reply with quote



Catalin Marinas wrote:
Quote:
Below is an example of some simple lambda expressions (but no
closures) using gcc's feature of brace-enclosed compound statements
inside of parentheses. The advantage over Boost.Lambda is that you can
write a full block of code and the arguments (_1, _2 etc.) are the
same as the lambda function arguments. The disadvantage is that it
doesn't allow closures (probably using functors instead of functions
but I haven't tried it yet).

Would braces inside parentheses be allowed by any future C++ standard?

Thanks.


#include <iostream
#include <vector

using namespace std;

#define lambda1(out_type, in_type, body) \
({ \
struct local_ { \
static out_type local_fn_(in_type _1) \
{ \
body; \
} \
}; \
&local_::local_fn_; \
})

int main()
{
vector<unsigned int> v;
v.push_back(0);
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);

// increment the vector elements
for_each(v.begin(), v.end(), lambda1(void, unsigned int&, ++_1));

// print the vector elements
for_each(v.begin(), v.end(),
lambda1(void, unsigned int, cout << _1 << endl));

// print the factorial of each element in the vector
for_each(v.begin(), v.end(),
lambda1(void, unsigned int,
cout << "factorial(" << _1 << ") = "
lambda1(unsigned int, unsigned int,
unsigned int fact = 1;
for (unsigned int i = 2; i <= _1;
++i)
{
fact *= i;
}
return fact)(_1)
endl));

return 0;
}


I believe this is too triky to be addded to C++. For example, consider
the following two cases:
for_each( v.begin(), v.end(), {} );
for_each( v.begin(), v.end(), {struct{}; struct{}; int x;} );

What is the type, and what is the _runtime_ value of the third
parameter?

Still, the folowing proposal comes into my mind now:

template <typename T>
void f(T param) {}

int main()
{
f(int()); // (1)

struct
{
void operator()(int i)
{
cout << i << endl;
}
} var; // (2)
f(var); // (3)

f(struct
{
void operator()(int i)
{
cout << i << endl;
}
}()
); // (4)

return 0;
}

(1), (2) and (3) work perfectly, but (4) seems to fail to compile. The
fourth point is somehow a combination of (1), (2) and (3). In (4) we
would have an anonymous struct and a temporary variable of that type.

If the C++ standard would allow constructs like (4), you get some nice
lambda expressions.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Lucian Radu Teodorescu
Guest





PostPosted: Fri Sep 01, 2006 5:48 pm    Post subject: Re: Simple lambda expressions (gcc only) Reply with quote



Catalin Marinas wrote:
Quote:
I believe this is too triky to be addded to C++. For example, consider
the following two cases:
for_each( v.begin(), v.end(), {} );
for_each( v.begin(), v.end(), {struct{}; struct{}; int x;} );

What is the type, and what is the _runtime_ value of the third
parameter?

The expression generated by the lambda macro is "({...})" and its
return type is a pointer to a function (the last line in the
macro). The return value is a pointer to a static function, defined in
a local class (I read about the trick with static functions inside
local classes in the Modern C++ Design book). Your examples above are
a bit different.

Sorry, but I don't understand how your reply answers my question. It
seems to me that you are explaining what the macro does, and not how
C++ should handle my for_each examples.

Are you trying to say that for both for_each statements, two functions
are generated that have the same body as the code passed to for_each?
If so, what are the parameters and the return type for generated
functions?

Quote:

Still, the folowing proposal comes into my mind now:

template <typename T
void f(T param) {}

int main()
{
f(int()); // (1)

struct
{
void operator()(int i)
{
cout << i << endl;
}
} var; // (2)
f(var); // (3)

(3) shouldn't work because you can't instantiate a template with the
type of a locally defined class (I think it is 14.3.9 in the standard
but not sure). This actually fails with gcc.

f(struct
{
void operator()(int i)
{
cout << i << endl;
}
}()
); // (4)

return 0;
}

(1), (2) and (3) work perfectly, but (4) seems to fail to compile. The
fourth point is somehow a combination of (1), (2) and (3). In (4) we
would have an anonymous struct and a temporary variable of that
type.

If the C++ standard would allow constructs like (4), you get some nice
lambda expressions.

Since (3) is not supported by the current standard, (4) wouldn't make
much sense.


I believe that this limatation you described is too severe. There is
already a proposal to eliminate this from the C++ standard:
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1427.pdf

I must admit that I haven't fully read the proposal yet, and I don't
know too much why this restriction was imposed in the first place, and
how this proposal will affect other parts of the standard.

If this proposal is adopted, the case (3) will work, and thus, making
point (4) a nice-to-have feature.

Best regards,
Lucian Radu Teodorescu


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Guest






PostPosted: Sat Sep 02, 2006 1:30 am    Post subject: Re: Simple lambda expressions (gcc only) Reply with quote

Hi Lucian,

Lucian Radu Teodorescu wrote:
Quote:
Catalin Marinas wrote:
I believe this is too triky to be addded to C++. For example, consider
the following two cases:
for_each( v.begin(), v.end(), {} );
for_each( v.begin(), v.end(), {struct{}; struct{}; int x;} );

What is the type, and what is the _runtime_ value of the third
parameter?

The expression generated by the lambda macro is "({...})" and its
return type is a pointer to a function (the last line in the
macro). The return value is a pointer to a static function, defined in
a local class (I read about the trick with static functions inside
local classes in the Modern C++ Design book). Your examples above are
a bit different.

Sorry, but I don't understand how your reply answers my question. It
seems to me that you are explaining what the macro does, and not how
C++ should handle my for_each examples.

It didn't answer you question directly, I just explained the types in
my examples. It looks like gcc considers the type and value of ({...})
to be the type and value of the last statement in the expression. In
your case (if you add the parenthesis, not just the braces), they
should probably be void (not sure whether the last one should be an
"int").

Quote:
Are you trying to say that for both for_each statements, two functions
are generated that have the same body as the code passed to for_each?
If so, what are the parameters and the return type for generated
functions?

I think I'm repeting myself but in my examples there is no code passed
to for_each. The last for_each argument in my examples is a pointer to
a function (void (*)(unsigned int)) and not a block of code which has
no type. There is only one template instantiation of the for_each
function as all the cases pass the same pointer-to-function argument.
For each lambda() macro call, a static function would be defined in
your program.

Your "for_each( v.begin(), v.end(), {} );" example would mean that
blocks of code are first-class entities which I don't think you find
even in functional languages (you have functions as first-class
entities but not a block of code) as you can't really guess the input
types (for the return type, you could assume is the type of the last
expression).

You other examples are nice but it would require a bigger change than
what I posted (which is already OK in gcc).

Numai bine :-)

Catalin


[ 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.