From -614276303725283451
X-Google-Thread: 7894ca11fe,d47b345505a72a70
X-Google-Attributes: gid7894ca11fe,public,usenet
X-Google-NewGroupId: yes
X-Google-Language: ENGLISH,ASCII-7-bit
Path: g2news2.google.com!news1.google.com!newsfeed.stanford.edu!news.kjsl.com!news.alt.net!frodo.cs.rpi.edu!not-for-mail
From: ymett <ymett.on.usenet@gmail.com>
Newsgroups: comp.std.c++
Subject: Re: for-else: adding else to for loops
Date: Thu, 27 Aug 2009 16:45:55 CST
Organization: http://groups.google.com
Lines: 107
Sender: cppmods@cs.rpi.edu
Approved: stephen.clamage@sun.com
Message-ID: <517a939e-9294-44c2-a489-99753116cff8@z24g2000yqb.googlegroups.com>
References: <8763cwvjjg.fsf@mid.deneb.enyo.de>
  <memo.20090814212024.1380A@brangdon.cix.compulink.co.uk>
NNTP-Posting-Host: netlab.cs.rpi.edu
Content-Type: text/plain; charset=ISO-8859-1
To: (Usenet)
Return-Path: <cppmods@ruralroute.cs.rpi.edu>
X-Original-Date: Thu, 27 Aug 2009 05:50:31 -0700 (PDT)
X-Submission-Address: std-c++@netlab.cs.rpi.edu
Xref: g2news2.google.com comp.std.c++:1320

On Aug 15, 10:36 pm, brang...@cix.co.uk (Dave Harris) wrote:
> f...@deneb.enyo.de (Florian Weimer) wrote (abridged):
>
> > > for (auto i : seq) {
> > >      for one { cout << "The only number is " << i << '\n'; }
> > >      for first { cout << "The numbers are " << i; }
> > >      for last { cout << " and " << i << '\n'; }
> > >      for others { cout << ", " << i; }
> > > }
> > > for none {cout << "There are no numbers\n";}
>
> > Is this really necessary when you have lambda expressions in the
> > language?
>
> Good question. I would love to see this done with lambda expressions, as
> a demonstration or test of what they, and C++0x, are capable of. (I don't
> feel competent to do it myself.)

template<class Range,
   class One, class First, class Last, class Other, class None>
void for_(Range&& range,
   One one, First first, Last last, Other other, None none)
{
   auto next = begin(range);
   if (next == end(range))
   {
     none();
     return;
   }
   auto current = next;
   ++next;
   if (next == end(range))
   {
     one(*current);
     return;
   }
   first(*current);
   while (current = next, ++next, next != end(range))
     other(*current);
   last(*current);
}

To be used as follows:

for_(seq,
      [](int i){ cout << "The only number is " << i << '\n'; },
      [](int i){ cout << "The numbers are " << i; },
      [](int i){ cout << " and " << i << '\n'; },
      [](int i){ cout << ", " << i; },
      []{cout << "There are no numbers\n";}
);

Some wrapper classes might make it look a little nicer:

template<class F> struct for_one_t { F f; };
template<class F> for_one_t<F> for_one(F f)
{ return for_one_t{f}; }

and likewise for for_first, for_last, for_others, and for_none.

Change the declaration to:

template<class Range,
   class One, class First, class Last, class Other, class None>
void for_(Range&& range, for_one_t<One> one,
   for_first_t<First> first, for_last_t<Last> last,
   for_others_t<Other> other, for_none_t<None> none);

(with appropriate changes to the definition) and you can write:

for_(seq,
   for_one([](int i){ cout << "The only number is " << i << '\n'; }),
   for_first([](int i){ cout << "The numbers are " << i; }),
   for_last([](int i){ cout << " and " << i << '\n'; }),
   for_others([](int i){ cout << ", " << i; }),
   for_none([]{cout << "There are no numbers\n";})
);

If you want to be able to omit some parts or to repeat some parts
that'll take a little more work (starting with defining exactly which
parts can appear where).

Unfortunately you have to repeat the element type (no auto available
there). Anyone for polymorphic lambdas?

Perhaps:

int i;
for_(i, seq,
   for_one([&]{ cout << "The only number is " << i << '\n'; }),
   for_first([&]{ cout << "The numbers are " << i; }),
   for_last([&]{ cout << " and " << i << '\n'; }),
   for_others([&]{ cout << ", " << i; }),
   for_none([]{cout << "There are no numbers\n";})
);

Implementation is left as an exercise for the reader.

Yechezkel Mett


-- 
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]



