When to prefer "for_each"?

S

Stefan Ram

In the web, I found a text claiming that

for( ...::iterator i = ....begin(); ... )...

was »old C++«, while

for_each( ..., [&]... )...

was »new C++«. So, in the general case, is there any advantage
in using »for_each« instead of »for« for such loops?
 
A

Alf P. Steinbach

In the web, I found a text claiming that

for( ...::iterator i = ....begin(); ... )...

was »old C++«, while

for_each( ..., [&]... )...

was »new C++«. So, in the general case, is there any advantage
in using »for_each« instead of »for« for such loops?

I hate code that uses those named traversal algorithms.

Instead I prefer the C++11 range based `for`, like

for( auto elem : vec ) { blah blah }

It's pretty trivial to define a range function for integer ranges and
code up Python-like loops, and the last time I checked, when I let the
compiler optimize that produced machine code like an ordinary `for`. Of
course YMMV. I tested it with Visual C++.


Cheers & hth.,

- Alf
 
V

Victor Bazarov

In the web, I found a text claiming that

for( ...::iterator i = ....begin(); ... )...

was »old C++«, while

for_each( ..., [&]... )...

was »new C++«. So, in the general case, is there any advantage
in using »for_each« instead of »for« for such loops?

'for_each' is a function call. It's a simplified version of the 'for'
loop. For instance, it's not as simple to bail out of 'for_each' as
writing 'break' in a 'for' loop (or a 'while' or 'do' loops).

V
 
A

Alf P. Steinbach

Which is great when you want to traverse only a sub-range, you want
to traverse it backwards, you only have input iterators...

I agree, it's simply great. :)


No, no, no; no need to wait for C++14.

For there is ample existing practice to draw on, e.g. Python programmers
do the above all the time, so that one already knows the general shape
of things.

It's just a matter of defining the requisite support machinery.

For example, for the task of reading from an input stream one can define


Code:
namespace cppx {
using std::istream;
using std::istream_iterator;
using std::ostream;
using std::ostream_iterator;
using std::string;

template< class Value >
class Istream_reader
// :public Non_copyable
{
private:
istream*    p_stream_;

public:
typedef istream_iterator< Value > It;

auto begin() const -> It { return It( *p_stream_ ); }
auto end() const -> It { return It(); }
Istream_reader( istream& stream ): p_stream_( &stream ) {}
};
}  // namespace cppx


And then instead of code like


Code:
auto main() -> int
{
using namespace std;
typedef istream_iterator<string> Init;
typedef ostream_iterator<string> Outit;

cout << "? ";
vector<string> words;
copy( Init( cin ), Init(), back_inserter( words ) );
cout << words.size() << " words:" << endl;
copy( words.begin(), words.end(), Outit( cout, "\n" ) );
}
[code]


one can write, much more clear in IMHO, and certainly easier to code for
me!,


[code]
auto main() -> int
{
using namespace std;
using namespace cppx;
typedef Istream_reader<string> Reader;

cout << "? ";
vector<string> words;
for( auto s : Reader( cin ) ) { words.emplace_back( s ); }
cout << words.size() << " words:" << endl;
for( auto s: words ) { cout << s << "\n"; }
}


which does the same, just more readable and writeable. ;-)


Cheers & hth.,

- Alf

PS: can the reader think of a simple support for "reverse range"?
 
V

Victor Bazarov

Alf P. Steinbach said:
For example, for the task of reading from an input stream one can define

Code:
namespace cppx {
using std::istream;
using std::istream_iterator;
using std::ostream;
using std::ostream_iterator;
using std::string;

template< class Value >
class Istream_reader
// :public Non_copyable
{
private:
istream*    p_stream_;

public:
typedef istream_iterator< Value > It;

auto begin() const -> It { return It( *p_stream_ ); }
auto end() const -> It { return It(); }
Istream_reader( istream& stream ): p_stream_( &stream ) {}
};
}  // namespace cppx

I really don't understand your point. You wrote something like 8 no-op
lines in that example that do absolutely nothing, plus a bunch of
unneeded syntax... for what purpose, exactly? To deliberately make it
look more complicated than it really needs to be? Why?

My point was: The range-based for cannot be used in all situations,
in which case you have to use a regular for. What exactly is your point?

I think it comes down to Rube Goldberg's rule: why use anything simple
and straightforward when a complex and convoluted method can accomplish
the same task? Impress the unwashed masses with the complexity and earn
respect and admiration of many...

V
 
M

Martin Shobe

Alf P. Steinbach said:
For example, for the task of reading from an input stream one can define

Code:
namespace cppx {
using std::istream;
using std::istream_iterator;
using std::ostream;
using std::ostream_iterator;
using std::string;

template< class Value >
class Istream_reader
// :public Non_copyable
{
private:
istream*    p_stream_;

public:
typedef istream_iterator< Value > It;

auto begin() const -> It { return It( *p_stream_ ); }
auto end() const -> It { return It(); }
Istream_reader( istream& stream ): p_stream_( &stream ) {}
};
}  // namespace cppx

I really don't understand your point. You wrote something like 8 no-op
lines in that example that do absolutely nothing, plus a bunch of
unneeded syntax... for what purpose, exactly? To deliberately make it
look more complicated than it really needs to be? Why?

My point was: The range-based for cannot be used in all situations,
in which case you have to use a regular for. What exactly is your point?

He just showed you how to use a range-based for in a situation you said
it couldn't be used in. That would be his point.

Martin Shobe
 
V

Victor Bazarov

Alf P. Steinbach said:
For example, for the task of reading from an input stream one can define

Code:
namespace cppx {
using std::istream;
using std::istream_iterator;
using std::ostream;
using std::ostream_iterator;
using std::string;

template< class Value >
class Istream_reader
// :public Non_copyable
{
private:
istream*    p_stream_;

public:
typedef istream_iterator< Value > It;

auto begin() const -> It { return It( *p_stream_ ); }
auto end() const -> It { return It(); }
Istream_reader( istream& stream ): p_stream_( &stream ) {}
};
}  // namespace cppx

I really don't understand your point. You wrote something like 8 no-op
lines in that example that do absolutely nothing, plus a bunch of
unneeded syntax... for what purpose, exactly? To deliberately make it
look more complicated than it really needs to be? Why?

My point was: The range-based for cannot be used in all situations,
in which case you have to use a regular for. What exactly is your point?

He just showed you how to use a range-based for in a situation you said
it couldn't be used in. That would be his point.

What's the saying, "don't use a cannon to kill a mosquito"?

V
 
A

Alf P. Steinbach

Alf P. Steinbach said:
For example, for the task of reading from an input stream one can define

Code:
namespace cppx {
using std::istream;
using std::istream_iterator;
using std::ostream;
using std::ostream_iterator;
using std::string;

template< class Value >
class Istream_reader
// :public Non_copyable
{
private:
istream*    p_stream_;

public:
typedef istream_iterator< Value > It;

auto begin() const -> It { return It( *p_stream_ ); }
auto end() const -> It { return It(); }
Istream_reader( istream& stream ): p_stream_( &stream ) {}
};
}  // namespace cppx

I really don't understand your point. You wrote something like 8 no-op
lines in that example that do absolutely nothing, plus a bunch of
unneeded syntax... for what purpose, exactly? To deliberately make it
look more complicated than it really needs to be? Why?

My point was: The range-based for cannot be used in all situations,
in which case you have to use a regular for. What exactly is your point?

I think it comes down to Rube Goldberg's rule: why use anything simple
and straightforward when a complex and convoluted method can accomplish
the same task? Impress the unwashed masses with the complexity and earn
respect and admiration of many...

To quote Martin Shobe in this same subthread:


"He just showed you how to use a range-based for in a situation you said
it couldn't be used in. That would be his point."


I'm surprised at you, Victor.

You know that comments such as yours, which mainly go to imagined
motives of a person, and in a derogatory fashion, would NEVER be
accepted in clc++m. Furthermore what little you provide of technical
assessment is incorrect. The code above is utterly trivial, ad simple as
possible, on the other end of the scale from "complex".

And as shown in the the context removed, the above code not only allows
a range based for to do the input iterator job, which is contrary to
Juha's assertion, proving him wrong, but

it also simplifies and clarifies that code.


Cheers,

- Alf (pretty disappointed, both about Juha's reaction to being proved
wrong, and about your follow-up false statements and imagined motives).
 
G

Geoff

- Alf (pretty disappointed, both about Juha's reaction to being proved
wrong, and about your follow-up false statements and imagined motives).

So where are the plinks?
 
V

Victor Bazarov

I'm surprised at you, Victor.

I am glad I'm not as predictable as some. Keeps my peers entertained
and on their toes.
You know that comments such as yours, which mainly go to imagined
motives of a person, and in a derogatory fashion, would NEVER be
accepted in clc++m.

Derogatory? What's derogatory in my comment? Please elaborate. And
consider please that my comment was not intended for c.l.c++.m, so there
is no particular value in your assessment. My comment wouldn't be
accepted as a doctoral dissertation either. So what?
Furthermore what little you provide of technical
assessment is incorrect. The code above is utterly trivial, ad simple as
possible, on the other end of the scale from "complex".

That's your opinion. You're just entitled to it as I am to mine.
And as shown in the the context removed, the above code not only allows
a range based for to do the input iterator job, which is contrary to
Juha's assertion, proving him wrong, but

it also simplifies and clarifies that code.

Again, that's your opinion.
Cheers,

- Alf (pretty disappointed, both about Juha's reaction to being proved
wrong, and about your follow-up false statements and imagined motives).

"False statements"? Care to show what's false about them?

You apparently developed highly sensitive ego in the last couple of
years. It makes interaction on the technical level rather difficult and
most certainly unpleasant. Disappointed? Based on what, your
expectation that people should always agree with you?

V
 
A

Alf P. Steinbach

On 11/19/2013 9:26 AM, Juha Nieminen wrote:
[...]
I'm surprised at you, Victor.

I am glad I'm not as predictable as some. Keeps my peers entertained
and on their toes.
You know that comments such as yours, which mainly go to imagined
motives of a person, and in a derogatory fashion, would NEVER be
accepted in clc++m.

Derogatory? What's derogatory in my comment? Please elaborate. And
consider please that my comment was not intended for c.l.c++.m, so there
is no particular value in your assessment. My comment wouldn't be
accepted as a doctoral dissertation either. So what?
Furthermore what little you provide of technical
assessment is incorrect. The code above is utterly trivial, ad simple as
possible, on the other end of the scale from "complex".

That's your opinion. You're just entitled to it as I am to mine.
And as shown in the the context removed, the above code not only allows
a range based for to do the input iterator job, which is contrary to
Juha's assertion, proving him wrong, but

it also simplifies and clarifies that code.

Again, that's your opinion.
Cheers,

- Alf (pretty disappointed, both about Juha's reaction to being proved
wrong, and about your follow-up false statements and imagined motives).

"False statements"? Care to show what's false about them?

I did. You called the code complex. But e.g. a function that returns a
value can't be simpler than just returning that value, as in that code.

Also your speculations about my motives for posting that technical
correction, were false.

You apparently developed highly sensitive ego in the last couple of
years.

Why do you persist in this person-oriented attack?

It's dumb.

Well unless you're trying to drown the earlier technical discussion,
proving Juha wrong, in noise?

It makes interaction on the technical level rather difficult and
most certainly unpleasant.

Your two postings in this thread, focusing mainly on person and IMAGINED
failings at that, are very unpleasant.

Disappointed? Based on what, your
expectation that people should always agree with you?

I'm disappointed that you did an all-out personal attack.

I'm disappointed that you did that that with no apparent cause
whatsoever, no prior interaction for months, as I recall (and our
history of interactions has not lately been antagonistic, quite the
opposite).

I'm now also disappointed that instead of apologizing, you're persisting
with more personal attacks, more imagined personal failings.

Whatever got into you?

Going native?


Cheers,

- Alf (not plonking you yet)
 
V

Victor Bazarov

[..]
Whatever got into you?

Into *me*? Look in the mirror, man. Ask yourself that question.
- Alf (not plonking you yet)

You know what? Get over it! Crawl out of that cave of yours, and enjoy
the world with the rest of us. Lighten up!

I appreciate your sharing of your opinions here. I am sure other folks
do, as well. I don't appreciate your attitude and your accusations.

Good luck!

V
 
A

Alf P. Steinbach

[..]
Whatever got into you?

Into *me*? Look in the mirror, man. Ask yourself that question.

You sound angry.

You know what? Get over it! Crawl out of that cave of yours, and enjoy
the world with the rest of us. Lighten up!

I appreciate your sharing of your opinions here. I am sure other folks
do, as well. I don't appreciate your attitude and your accusations.

After two postings with only personal attacks, with nothing technical
except one absurd assessment of complexity, you make a third posting
where you remove all context and make even further personal attacks.

I think a good way to limit the noise, from you and from me in response
to you, is for me to not see your postings here anymore.

The three posting that you have made in this thread (and I can't recall
seeing other postings in the last weeks) have not contributed anything
technical. And you have stated that you now find trivial code to be very
complex, so I'm not expecting to miss any learning. And in the other
direction, with that stream of ad hominem attacks I doubt that you would
have been willing to learn anything technical from me, so.


Sorry about this,

- Alf (plonking you)
 
M

Martin Shobe

For example, for the task of reading from an input stream one can
define

Code:
namespace cppx {
using std::istream;
using std::istream_iterator;
using std::ostream;
using std::ostream_iterator;
using std::string;

template< class Value >
class Istream_reader
// :public Non_copyable
{
private:
istream*    p_stream_;

public:
typedef istream_iterator< Value > It;

auto begin() const -> It { return It( *p_stream_ ); }
auto end() const -> It { return It(); }
Istream_reader( istream& stream ): p_stream_( &stream ) {}
};
}  // namespace cppx

I really don't understand your point. You wrote something like 8 no-op
lines in that example that do absolutely nothing, plus a bunch of
unneeded syntax... for what purpose, exactly? To deliberately make it
look more complicated than it really needs to be? Why?

My point was: The range-based for cannot be used in all situations,
in which case you have to use a regular for. What exactly is your point?

He just showed you how to use a range-based for in a situation you said
it couldn't be used in. That would be his point.

What's the saying, "don't use a cannon to kill a mosquito"?

Irrelevant to the matter at hand. Especially since he appears to have
the complexity buried in a library. Relatively complex code can be
tolerated there if it reduces complexity in enough other places. (I'm
not sure I'd use his code, as I don't need to read in a stream word by
word often enough. Still, his general point about range-based for stands.)

Martin Shobe
 
V

Victor Bazarov

[..] Still, his general point about range-based for stands.

"General point"? That range-based 'for' *can* be used with input
iterators? <shrug> With enough additional code, anything is possible.
If you already have a car (code buried in a library), you *can* enjoy
faster travel and more carrying capacity than when using a bicycle (or
compared to running with a backpack). But if you're deciding *right
now* what to use to get somewhere, you might consider starting walking
instead of trying to spend time building a vehicle of some kind. That's
all.

V
 
Ö

Öö Tiib

On Monday, 18 November 2013 22:30:54 UTC+2, Alf P. Steinbach wrote:

Snip the class it was simple but I try to emphasise differences caused by
usage of the class:
And then instead of code like

copy( istream_iterator<string>( cin )
one can write, much more clear in IMHO, and certainly easier to code for

for( auto s : Istream_reader<string>( cin ) )
{
words.emplace_back( s );
}
which does the same, just more readable and writeable. ;-)

I read first "copy strings from cin inserting to back of words" and second I
read "for each string in istream reader of cin emplace it to back of words".

Latter does not look like notable improvement ... the more usual code
changed to less usual. I'd accuse in needless over-engineering in review.
 
I

Ian Collins

The standards on clc++m have slipped significantly recently (google
crap, gratuitous snipping of attributions), so you never know...
Why do you persist in this person-oriented attack?

This is Usenet! Lighten up.
 
A

Alf P. Steinbach

You wrote it twice as lengthy and complicated than it needs to be,

The line and statement counts were the same for algorithm and range for
versions, so

unless you mean that the range based for version could be even smaller
(half the size) and simpler, your statement doesn't make much sense.

Is it the case, that you really mean that the range based for version
could be half the size?

and you say that it "simplifies and clarifies that code"?

Yes. :)

Cheers & hth.,

- Alf
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top