468,503 Members | 2,126 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,503 developers. It's quick & easy.

std::for_each + break

Hi

I wanna give template method of library class with some predicate,
which I put to std::for_each in that method.How to break the
std::for_each with predicate?(exceptions are used olny in exceptional
situations, as i know)

Thanks
Nov 19 '07 #1
22 5704
On Nov 19, 8:12 pm, yurec <Yurij.Zha...@materialise.kiev.uawrote:
Hi

I wanna give template method of library class with some predicate,
which I put to std::for_each in that method.How to break the
std::for_each with predicate?(exceptions are used olny in exceptional
situations, as i know)

Thanks
Perhaps you would be better served by std::find_if
Nov 19 '07 #2
On Nov 19, 2:17 pm, alan <almkg...@gmail.comwrote:
On Nov 19, 8:12 pm, yurec <Yurij.Zha...@materialise.kiev.uawrote:
Hi
I wanna give template method of library class with some predicate,
which I put to std::for_each in that method.How to break the
std::for_each with predicate?(exceptions are used olny in exceptional
situations, as i know)
Thanks

Perhaps you would be better served by std::find_if
For sure, thx
Nov 19 '07 #3
On Nov 19, 1:12 pm, yurec <Yurij.Zha...@materialise.kiev.uawrote:
I wanna give template method of library class with some
predicate, which I put to std::for_each in that method.How to
break the std::for_each with predicate?(exceptions are used
olny in exceptional situations, as i know)
You can't. That's precisely the point of for_each.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Nov 20 '07 #4
On 2007-11-19 07:12:29 -0500, yurec <Yu**********@materialise.kiev.uasaid:
Hi

I wanna give template method of library class with some predicate,
which I put to std::for_each in that method.How to break the
std::for_each with predicate?(exceptions are used olny in exceptional
situations, as i know)

Thanks
I would think throwing an exception is a simple and elegant solution here.

Just because we have called a mechanism 'exception' and gave it the
connotation that it is for error-handling purposes, does not mean that
we can only use the mechanism as such and nothing else.

Ok, so some runtime cost is needed to setup try-catch blocks, but I'm
not sure scanning the list twice with find_if/for_each combo is
necessarily faster.

--

-kira

Nov 20 '07 #5
/* doesn't compile :(
maybe somebody knows where is my mistake?

using namespace boost::lambda;
get_layout_func_map::const_iterator iter_func =
std::find_if(named_func_map.begin(), named_func_map.end(),

bind(&IContextToLayoutPred::Compare, ip_pred,

bind(&get_layout_func_map::value_type::second, _1)));
*/

//compiles ok!
get_layout_func_map::const_iterator iter_func =
named_func_map.begin();
const get_layout_func_map::const_iterator iter_func_end =
named_func_map.end();
while (iter_func_end != iter_func)
{
if (true == ip_pred->Compare(iter_func->second))
break;

++iter_func;
}
Nov 20 '07 #6
On Tue, 20 Nov 2007 11:04:40 -0800, James Kanze wrote:
Anyone who wrote that at any place where I've ever worked would not be
allowed to touch the code again. Exceptions are NOT a flow control
mechanism.
You should look at the Boost Graph Library's visitor mechanism then. From
what I recall, it used exceptions to stop visiting something or the other.

:-)

--
Sohail Somani
http://uint32t.blogspot.com
Nov 20 '07 #7
On 2007-11-20 14:04:40 -0500, James Kanze <ja*********@gmail.comsaid:
On Nov 20, 1:13 pm, Kai-Uwe Bux <jkherci...@gmx.netwrote:
>terminator wrote:
>>On Nov 20, 12:45 pm, Kai-Uwe Bux <jkherci...@gmx.netwrote:
>>>try {
std::for_each( seq.begin(), seq.end(), throwing_predicate_and_actio
n
>>>);
}
catch ( whatever ) {}

Anyone who wrote that at any place where I've ever worked would
not be allowed to touch the code again. Exceptions are NOT a
flow control mechanism.
Any boss who think like that I would not want to work for.

Exception is certainly a flow control mechanism. Essentially it is a
glorified longjmp with smart stack unwinding that invokes destructors.
If it looks like a duck and quakes like a duck, then it is a duck.

Now of course, the question remains when is the proper use of such type
of flow control. Is it *always* only valid for error handling purposes
and nothing else? That I cannot say I have enough experience to
answer, but I find it hard to believe that there is no other uses of an
inter-stackframe branching mechanism that is aware of cleaning up
objects in those frames, beside error handling.

But I like to bring up one possible use:

In some of the algorithm books I've been reading, many of them have
terminating statements (like 'return') nested deeply in nested loops.
So, once a certain terminating condition is reached, the entire
algorithm is done and exited. If the entire algorithm has been
implemented in a single function, then the 'return' statement is
sufficient to exit the algorithm. But what if helper functions were
used and that the terminating conditions are inside these helper
functions? In this case, you can either have the helper functions
return a terminating return code or you can have the main function
setup a try-catch block and let the helper function throw an exception.
Now imagine what if helper functions can have helper functions too.
Don't you think throwing an exception here is the easiest way to return
control to the main function?

Of course, some people believe that 'return' statements should never be
in the middle of a function. A good implementation of an algorithm
would have every control flow reach the last statement before the
function-ending braces. If this is your philosophy, then to you
exception-handling should be used for error-purposes only.
>
[...]
--

-kira

Nov 20 '07 #8
On 2007-11-20 04:45:36 -0500, Kai-Uwe Bux <jk********@gmx.netsaid:
Kira Yamato wrote:
>On 2007-11-19 07:12:29 -0500, yurec <Yu**********@materialise.kiev.ua>
said:
>>Hi

I wanna give template method of library class with some predicate,
which I put to std::for_each in that method.How to break the
std::for_each with predicate?(exceptions are used olny in exceptional
situations, as i know)

Thanks

I would think throwing an exception is a simple and elegant solution here.

Simple and elegant? in this case?

Compare

try {
std::for_each( seq.begin(), seq.end(), throwing_predicate_and_action );
}
catch ( whatever ) {}

to

for ( iterator_type iter = seq.begin();
iter != seq.end() && ! break_condition( *iter );
++iter ) {
some_action( *iter );
}

I cannot say that I find the try-throw-catch version easier to grok or more
elegant.
Hmm. The for-loop code looks more explicit than the for_each. So, why
do we bother with for_each again?

Or I should ask, why would we ever prefer a statement over a block?
>
[...]
--

-kira

Nov 20 '07 #9
On Tue, 20 Nov 2007 15:51:12 -0500, Kira Yamato wrote:
Hmm. The for-loop code looks more explicit than the for_each. So, why
do we bother with for_each again?

Or I should ask, why would we ever prefer a statement over a block?
Because it is easier to understand statements than instructions. Compare:

namespace bl=boost::lambda; http://www.boost.org/doc/html/lambda.html
....
std::transform(vec1.begin(),vec1.end(),vec2.begin( ),bl::_1 + 1);

To:

for(int i = 0; i < vec1.size(); ++i)
{
vec2[i] = vec2[i] + 1;
}

Over time, given enough use of the C++ standard library, you can gain an
understanding of what code is doing by casual reading without having to
scrutinize what the code is doing at the instruction level. So in the
first example, it is obvious from reading a single line of code, that
someone is intending to add 1 to each element in a vector and assign it
to another. I need to read and grok 5 lines for the second version.

At least that is my 2 minute explanation!

--
Sohail Somani
http://uint32t.blogspot.com
Nov 20 '07 #10
On Nov 20, 11:31 pm, yurec <Yurij.Zha...@materialise.kiev.uawrote:
/* doesn't compile :(
maybe somebody knows where is my mistake?

using namespace boost::lambda;
get_layout_func_map::const_iterator iter_func =
std::find_if(named_func_map.begin(), named_func_map.end(),

bind(&IContextToLayoutPred::Compare, ip_pred,

bind(&get_layout_func_map::value_type::second, _1)));
*/
Try creating a simple member function that returns the member data
'second' of a get_layout_func_map:
<your return type hereget_layout_func_map::get_second(){
return second;
}

then replace get_layout_func_map::value_type::second with
get_layout_func_map::get_second. As an aside, you might also
profitably add "inline" to the above member function, if you take care
to add the definition to the header file.

get_layout_func_map::value_type may not exist in your
get_layout_func_map class, and even if it does, it might not have a
member called second. Did you (or who created get_layout_func_map, or
one of its public base types) write such a member?

boost::bind requires the first argument to be either function or a
function object (i.e. belonging to a class that overloads the ()
operator or function call operator)
>
//compiles ok!
get_layout_func_map::const_iterator iter_func =
named_func_map.begin();
const get_layout_func_map::const_iterator iter_func_end =
named_func_map.end();
while (iter_func_end != iter_func)
{
if (true == ip_pred->Compare(iter_func->second))
break;

++iter_func;
}
This seems quite clear enough; using boost::bind may just make things
look more horrible.
Nov 20 '07 #11
On Nov 21, 4:51 am, Kira Yamato <kira...@earthlink.netwrote:
On 2007-11-20 04:45:36 -0500, Kai-Uwe Bux <jkherci...@gmx.netsaid:
Kira Yamato wrote:
On 2007-11-19 07:12:29 -0500, yurec <Yurij.Zha...@materialise.kiev.ua>
said:
>Hi
>I wanna give template method of library class with some predicate,
which I put to std::for_each in that method.How to break the
std::for_each with predicate?(exceptions are used olny in exceptional
situations, as i know)
>Thanks
I would think throwing an exception is a simple and elegant solution here.
Simple and elegant? in this case?
Compare
try {
std::for_each( seq.begin(), seq.end(), throwing_predicate_and_action );
}
catch ( whatever ) {}
to
for ( iterator_type iter = seq.begin();
iter != seq.end() && ! break_condition( *iter );
++iter ) {
some_action( *iter );
}
I cannot say that I find the try-throw-catch version easier to grok or more
elegant.

Hmm. The for-loop code looks more explicit than the for_each. So, why
do we bother with for_each again?
So we won't have to bother with iterators, which are just pointers in
pretty clothes?
>
Or I should ask, why would we ever prefer a statement over a block?
[...]

--

-kira
Nov 20 '07 #12
On Tue, 20 Nov 2007 22:26:10 +0100, Alf P. Steinbach wrote:
>std::transform(vec1.begin(),vec1.end(),vec2.begin (),bl::_1 + 1);

To:

for(int i = 0; i < vec1.size(); ++i)
{
vec2[i] = vec2[i] + 1;
}
>
The second code snippet is by far most clear and at-a-glance.

However, it caused me to look twice because it's so non-idiomatic,
Pascal style that at first glance one thinks there must be some reason
for that, that it doesn't do what it seems to: in C++ we use ++.
Sure! You also managed to miss the deliberate bug which was part of the
point :-)

--
Sohail Somani
http://uint32t.blogspot.com
Nov 20 '07 #13
On Tue, 20 Nov 2007 23:55:43 +0100, Alf P. Steinbach wrote:
* Sohail Somani:
>On Tue, 20 Nov 2007 23:03:46 +0100, Alf P. Steinbach wrote:
Then I guess that in your view the first snippet defined the wished for
effect, and the second had a "bug" in the sense that it didn't do the
same?

If so, then you're suffering from the "others should read my mind"
syndrome.
Dude chill. If you read the rest of the email, I did concede that! In
fact, its the next line you quote:
>but I suppose the example wasn't full enough. I'll let you off this
time.
[snip]
Grumble,
And how!

--
Sohail Somani
http://uint32t.blogspot.com
Nov 20 '07 #14
On Tue, 20 Nov 2007 17:18:24 -0800, Kai-Uwe Bux wrote:
However, it does not actually present any data in support of the claim
that generic algorithms tend to introduce the kind of bug you pointed
out.
I'm done with this thread, but I just want to point out that there was no
bug. That is an intended mode of use for std::transform: Perform an
operation on each element in an array and assign it to another.

--
Sohail Somani
http://uint32t.blogspot.com
Nov 21 '07 #15
On Wed, 21 Nov 2007 01:38:22 +0000, Sohail Somani wrote:
On Tue, 20 Nov 2007 17:18:24 -0800, Kai-Uwe Bux wrote:
>However, it does not actually present any data in support of the claim
that generic algorithms tend to introduce the kind of bug you pointed
out.

I'm done with this thread, but I just want to point out that there was
no bug. That is an intended mode of use for std::transform: Perform an
operation on each element in an array and assign it to another.
Damnit, here you go.

// file.cpp
#include <iostream>
#include <vector>
#include <boost/lambda/lambda.hpp>
#include <algorithm>

namespace bl = boost::lambda;

int main()
{
std::vector<intv1(10,5);
std::vector<intv2(10);
// v2[i] = v1[i] + 1 for i in [0,v2.size())
std::transform(v1.begin(),v1.end(),v2.begin(),bl:: _1 + 1);
std::for_each(v1.begin(),v1.end(),std::cout << bl::_1 << '\n');
std::for_each(v2.begin(),v2.end(),std::cout << bl::_1 << '\n');
}

Output:
5
5
5
5
5
5
5
5
5
5
6
6
6
6
6
6
6
6
6
6

--
Sohail Somani
http://uint32t.blogspot.com
Nov 21 '07 #16
On Nov 22, 10:14 am, Kai-Uwe Bux <jkherci...@gmx.netwrote:
terminator wrote:
[...]
I guess, the way to do this idiomatically in STLeese is something like:
std::for_each( begin, std::find_if( begin, end, condition ), action );
Now, I see that the OP did not specify whether there is a
need for performing an action on the elements of the
sequence or whether the task at hand is simply to find the
first where a condition holds. In the later case,
std::find_if is of course perfectly fine.
that is double looping :too much run time.
Before you come to that conclusion, you might want to measure.
Note that during the first loop, only the condition is
evaluated and during the second loop only the action is
evaluated. That means, as long as incrementing iterators is
cheap compared to evaluating the condition and performing the
action, the double looping is should not be expected to be
significantly more expensive.
Moreover, optimization in compilers has come a long way and I
wouldn't be surprised if the compiler would actually fold the
two loops into one (especially since the first is only used to
determine the upper bound for the second).
More likely it won't. You have two loops, each of which fits
into a cache line. Replacing it with a single, larger loop
which no longer fits into the cache line is *not* an
optimization.

Of course, the compiler knows about things like cache line
width, and will do the optimization if it improves things, and
not do it if it would slow them down.

[...]
Upthread, I suggested:
for ( ... ) {
...
}
and I still find it readable and fast.
And a really good compiler might even break it into two loops,
if that would speed things up:-).

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Nov 23 '07 #17
On Nov 23, 5:18 pm, James Kanze <james.ka...@gmail.comwrote:
On Nov 22, 10:14 am, Kai-Uwe Bux <jkherci...@gmx.netwrote:


terminator wrote:
[...]
>I guess, the way to do this idiomatically in STLeese is something like:
> std::for_each( begin, std::find_if( begin, end, condition ), action );
>Now, I see that the OP did not specify whether there is a
>need for performing an action on the elements of the
>sequence or whether the task at hand is simply to find the
>first where a condition holds. In the later case,
>std::find_if is of course perfectly fine.
that is double looping :too much run time.
Before you come to that conclusion, you might want to measure.
Note that during the first loop, only the condition is
evaluated and during the second loop only the action is
evaluated. That means, as long as incrementing iterators is
cheap compared to evaluating the condition and performing the
action, the double looping is should not be expected to be
significantly more expensive.
Moreover, optimization in compilers has come a long way and I
wouldn't be surprised if the compiler would actually fold the
two loops into one (especially since the first is only used to
determine the upper bound for the second).

More likely it won't. You have two loops, each of which fits
into a cache line. Replacing it with a single, larger loop
which no longer fits into the cache line is *not* an
optimization.

Of course, the compiler knows about things like cache line
width, and will do the optimization if it improves things, and
not do it if it would slow them down.

[...]
Upthread, I suggested:
for ( ... ) {
...
}
and I still find it readable and fast.

And a really good compiler might even break it into two loops,
if that would speed things up:-).
why should all the ways end to Roma?
why should we leave everything to destiny?
why should everything be left to compiler`s abilitiy to auto-optimize?
Nov 23 '07 #18
On Nov 23, 9:04 pm, terminator <farid.mehr...@gmail.comwrote:
On Nov 23, 5:18 pm, James Kanze <james.ka...@gmail.comwrote:
[...]
why should everything be left to compiler`s abilitiy to
auto-optimize?
Because they can do it so much better than a human.

Of course, they do sometimes fail; when the profiler says we
must, we optimize by hand. But historically, programmers have
been notoriously bad about optimizing without using the
profiler.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Nov 24 '07 #19
On Nov 24, 8:12 pm, James Kanze <james.ka...@gmail.comwrote:
On Nov 23, 9:04 pm, terminator <farid.mehr...@gmail.comwrote:
On Nov 23, 5:18 pm, James Kanze <james.ka...@gmail.comwrote:

[...]
why should everything be left to compiler`s abilitiy to
auto-optimize?

Because they can do it so much better than a human.

Of course, they do sometimes fail; when the profiler says we
must, we optimize by hand. But historically, programmers have
been notoriously bad about optimizing without using the
profiler.
Got it ,that junk profiler is not designed by a dumb human.
Nov 25 '07 #20
On Nov 25, 11:04 am, terminator <farid.mehr...@gmail.comwrote:
On Nov 24, 8:12 pm, James Kanze <james.ka...@gmail.comwrote:
On Nov 23, 9:04 pm, terminator <farid.mehr...@gmail.comwrote:
On Nov 23, 5:18 pm, James Kanze <james.ka...@gmail.comwrote:
[...]
why should everything be left to compiler`s abilitiy to
auto-optimize?
Because they can do it so much better than a human.
Of course, they do sometimes fail; when the profiler says we
must, we optimize by hand. But historically, programmers have
been notoriously bad about optimizing without using the
profiler.
Got it ,that junk profiler is not designed by a dumb human.
No you haven't gotten it. A human using a meter measuring stick
is a lot better at determining lengths that a human just
estimating. A profiler is a measuring instrument.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Nov 25 '07 #21
On Nov 25, 8:15 pm, James Kanze <james.ka...@gmail.comwrote:
On Nov 25, 11:04 am, terminator <farid.mehr...@gmail.comwrote:
On Nov 24, 8:12 pm, James Kanze <james.ka...@gmail.comwrote:
On Nov 23, 9:04 pm, terminator <farid.mehr...@gmail.comwrote:
On Nov 23, 5:18 pm, James Kanze <james.ka...@gmail.comwrote:
[...]
why should everything be left to compiler`s abilitiy to
auto-optimize?
Because they can do it so much better than a human.
Of course, they do sometimes fail; when the profiler says we
must, we optimize by hand. But historically, programmers have
been notoriously bad about optimizing without using the
profiler.
Got it ,that junk profiler is not designed by a dumb human.

No you haven't gotten it. A human using a meter measuring stick
is a lot better at determining lengths that a human just
estimating. A profiler is a measuring instrument.

--
James Kanze (GABI Software) email:james.ka...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
the question is whether to update the library or hope that the
compiler core is updated . I can not trust what I can not control.

regards,
FM.
Nov 26 '07 #22
terminator wrote:
On Nov 25, 8:15 pm, James Kanze <james.ka...@gmail.comwrote:
>On Nov 25, 11:04 am, terminator <farid.mehr...@gmail.comwrote:
On Nov 24, 8:12 pm, James Kanze <james.ka...@gmail.comwrote:
On Nov 23, 9:04 pm, terminator <farid.mehr...@gmail.comwrote:
On Nov 23, 5:18 pm, James Kanze <james.ka...@gmail.comwrote:
[...]
why should everything be left to compiler`s abilitiy to
auto-optimize?
Because they can do it so much better than a human.
Of course, they do sometimes fail; when the profiler says we
must, we optimize by hand. But historically, programmers have
been notoriously bad about optimizing without using the
profiler.
Got it ,that junk profiler is not designed by a dumb human.

No you haven't gotten it. A human using a meter measuring stick
is a lot better at determining lengths that a human just
estimating. A profiler is a measuring instrument.
[snip]
the question is whether to update the library or hope that the
compiler core is updated . I can not trust what I can not control.
Then I take it that you implemented your own tool chain?

Chess programs regularly outplay their programmers. In the same way,
compilers regularly generate code that is better adapted to the pipeline in
the processor than a human programmer would do. However, of course, you are
free to try. You would need to use assembler, though: as long as you use a
high level language, you won't have enough control over details. E.g., the
compiler will decide for you what to put into registers at which point.
Best

Kai-Uwe Bux
Nov 26 '07 #23

This discussion thread is closed

Replies have been disabled for this discussion.

By using this site, you agree to our Privacy Policy and Terms of Use.