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 

How to get arity from lamda expression?

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





PostPosted: Tue Jun 20, 2006 2:53 pm    Post subject: How to get arity from lamda expression? Reply with quote



After I learned some Ruby syntax, I could write the code that print
one's tables in a line like the following.

(2..9).each { |i| (1..9).each { |j| puts "#{i}*#{j}=#{i * j}" } }

So, I thought it's good to have something like this in C++.
The written code is this.

----
using namespace std;
using namespace boost;
using namespace boost::lambda;
using namespace boost::mpl;

class range
{
public:
range() {
}
range(int s, int e) {
s_.push_back(s);
e_.push_back(e);
}

range& operator()(int s, int e) {
s_.push_back(s);
e_.push_back(e);

return *this;
}

template <class F>
range& operator()(F func) {
// now this range only support 2-depth loop.
// but it can be extended.
typedef typename if_c<F::arity == 2, do_2, do_1>::type do_type;

do_type()(s_, e_, func);

return *this;
}

struct do_2
{
void operator()(vector<int>& s_, vector<int>& e_, function<void
(int, int)> func) {
for (int i = s_[0]; i <= e_[0]; ++i)
for (int j = s_[1]; j <= e_[1]; ++j)
func(i, j);
}
};

struct do_1
{
void operator()(vector<int>& s_, vector<int>& e_, function<void
(int)> func) {
for (int i = s_[0]; i <= e_[0]; ++i)
func(i);
}
};

private:
vector<int> s_;
vector<int> e_;
};

With this, I could write the print one's tables code like the
following.

function<void (int, int)> f(cout << _1 << '*' << _2 << '=' << _1 * _2
<< '\n');
range(2, 9)(1, 9)( f );

or

range(2, 9)(1, 9)( function<void (int, int)>(cout << _1 << '*' << _2 <<
'=' << _1 * _2 << '\n' ) );

But What I really want to do is using lamda directly as the parameter
like the below.

range(2, 9)(1, 9)( cout << _1 << '*' << _2 << '=' << _1 * _2 << '\n' );

But I can't find something like ::arity with the lambda expression.

Is there any solution? or is there already some 'range' class like
this?

----
And one more question.
In the documentation of lambda, the 'protect' function is introduced
with sample code.

int x = 1, y = 10;
(_1 + protect(_1 + 2))(x)(y);

But, I can't compile this with g++ 3.2.3.
The following is successfully compiled and the result id 12.

(protect(_1 + 2))(x)(y);

----
I found that the 'function_traits' can not be used with 'function.' I
wish it'll be compatible. :-)


Thanks in advance.

iwongu


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





PostPosted: Wed Jun 21, 2006 2:54 pm    Post subject: Re: How to get arity from lamda expression? Reply with quote



iwongu wrote:
Quote:
After I learned some Ruby syntax, I could write the code that print
one's tables in a line like the following.

(2..9).each { |i| (1..9).each { |j| puts "#{i}*#{j}=#{i * j}" } }

So, I thought it's good to have something like this in C++.
The written code is this.

----
using namespace std;
using namespace boost;
using namespace boost::lambda;
using namespace boost::mpl;

class range
{
public:
range() {
}
range(int s, int e) {
s_.push_back(s);
e_.push_back(e);
}

range& operator()(int s, int e) {
s_.push_back(s);
e_.push_back(e);

return *this;
}

template <class F
range& operator()(F func) {
// now this range only support 2-depth loop.
// but it can be extended.
typedef typename if_c<F::arity == 2, do_2, do_1>::type do_type;

do_type()(s_, e_, func);

return *this;
}

In principle, you don't need F::arity here; s_.size() tells you what to
do. Relying on arity, even if lambda objects did expose one (they don't
because they have a range of arities) would not allow you to express
the equivalent of

(2..9).each { |i| (1..9).each { |j| puts "#{i}" } }

where the arity of the lambda is one, but it is still used in two
nested loops. (This may or may not be valid Ruby code. Smile )

There's the problem of f( i ) not compiling for cout << _2, though; so
you'll need to drop the single dynamically-dimensioned range class and
return range2 or range<2> from operator()( int, int ).


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