 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
true_smart@hotmail.com Guest
|
Posted: Thu Jan 06, 2005 9:12 am Post subject: How to use for_each when the mem_fun's fun return "true" val |
|
|
following code segment is on the MSND and modified by me. I want to use
mem_fun(or other way) to run IsZeor if the function the IsZero retrun
ture then break for_each.
class StoreVals
{
int val;
public:
StoreVals () {val = 0;}
StoreVals (int j) {val = j;}
bool IsZeor(){cout<
};
int main( )
{
vector
v1.push_back(&StoreVals (5));
v1.push_back(&StoreVals (10));
v1.push_back(&StoreVals (15));
v1.push_back(&StoreVals (20));
v1.push_back(&StoreVals (0));
v1.push_back(&StoreVals (25));
for_each(v1.begin(), v1.end(), mem_fun<bool, StoreVals> (
&StoreVals::IsZeor));
cout << endl;
}
How to modify the code segment I can print: 5,10,15,20,0
but not print 5,10,15,20,0,25
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Alberto Barbati Guest
|
Posted: Thu Jan 06, 2005 6:58 pm Post subject: Re: How to use for_each when the mem_fun's fun return "true" |
|
|
[email]true_smart (AT) hotmail (DOT) com[/email] wrote:
| Quote: | following code segment is on the MSND and modified by me. I want to use
mem_fun(or other way) to run IsZeor if the function the IsZero retrun
ture then break for_each.
|
Your code is so full of other problems, that I would like to discuss
them with you before. Next time please post a piece of code that
actually compiles. It's full of typos... and doesn't do what you say it
should.
The need for class StoreVals is not clear to me. You should not need it.
Why didn't you just store ints in the vector and use a free functor?
| Quote: | {
int val;
public:
StoreVals () {val = 0;}
StoreVals (int j) {val = j;}
|
You can avoid the double constructor by writing
StoreVals (int j = 0) {val = j;}
| Quote: | | bool IsZeor(){cout<
|
IsZeor => IsZero and vla => val
The name IsZero is a misnomer, because it doens't only check if the
value is zero, but it has side-effects (prints to cout, in this case).
| Quote: | };
int main( )
{
vector <StoreVals *> v1;
v1.push_back(&StoreVals (5));
|
WHAT???? Are you crazy? You are inserting a pointer to a temporary
inside a vector! This is very bad! The temporary will be destroyed just
after the ";" so the address you just put in the vector will point to
rubbish. VERY undefined behaviour. In fact, on VC7.1 with release
settings, your program displays "25,25,25,25,25,25," and not
"5,10,15,20,0,25," but it might as well crash and the compiler would
still not be the one to blame.
If you want to use pointers, you should allocate the objects on the heap
with new as in:
v1.push_back(new StoreVals(5));
but then you you will be in big troubles when deleting the objects
(google for "Smart Container library" for an explanation). Much better
and simpler, you should declare v1 as holding objects, not pointers, as in:
vector<StoreVals> v1;
v1.push_back(StoreVals(5));
| Quote: | v1.push_back(&StoreVals (10));
v1.push_back(&StoreVals (15));
v1.push_back(&StoreVals (20));
v1.push_back(&StoreVals (0));
v1.push_back(&StoreVals (25));
for_each(v1.begin(), v1.end(), mem_fun<bool, StoreVals> (
&StoreVals::IsZeor));
|
Again IsZeor => IsZero.
Why did you write the template parameters explicitly? The mem_fun helper
function is there precisely to let the programmer omit them. So you
should write:
for_each(v1.begin(), v1.end(), mem_fun(&StoreVals::IsZero));
or, if you declare v1 as holding objects:
for_each(v1.begin(), v1.end(), mem_fun_ref(&StoreVals::IsZero));
| Quote: | cout << endl;
}
How to modify the code segment I can print: 5,10,15,20,0
but not print 5,10,15,20,0,25
|
The short the answer is: it's not possible. for_each does what its names
says: it applies the operation "for each" object. Not one more, not one
less.
The best things you can do, IMHO, are:
1) write the loop explicitly. In this case it's very simple, so using
for_each is not really an advantage
2) if you need to use this kind of algorithm very ofter, write it your own:
template
Func for_each_while_true(It first, It last, Func f)
{
for(; first != last; ++first)
if(!f(*first))
break;
return f;
}
However, if you really want to stick with for_each, there is indeed a
way to achieve what you want. It's not very elegant, IMHO, so I would
not recommend them, but I put it here for sake of completeness. It
throws an exception to abort the iteration:
Declare a dummy type like
struct abort_iteration {};
declare IsZero like this:
void IsZero() // the name IsZero is now a misnomer
{
cout << val << ",";
if(val == 0) throw abort_iteration();
}
then call it like this:
try
{
for_each(v1.begin(), v1.end(), mem_fun_ref(&StoreVals::IsZero));
}
catch(abort_iteration)
{}
HTH,
Alberto
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
msalters Guest
|
Posted: Thu Jan 06, 2005 7:03 pm Post subject: Re: How to use for_each when the mem_fun's fun return "true" |
|
|
[email]true_smart (AT) hotmail (DOT) com[/email] wrote:
| Quote: | following code segment is on the MSND and modified by me. I want to
use
mem_fun(or other way) to run IsZeor if the function the IsZero retrun
ture then break for_each.
|
So you really mean for_some( ), not for_each( ). That's no standard
function. Another solution could be a view iterator, which basically
redefines the end iterator to *underlying_iterator==0.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
dietmar_kuehl@yahoo.com Guest
|
Posted: Fri Jan 07, 2005 2:24 pm Post subject: Re: How to use for_each when the mem_fun's fun return "true" |
|
|
[email]true_smart (AT) hotmail (DOT) com[/email] wrote:
| Quote: | following code segment is on the MSND and modified by me. I want to
use
mem_fun(or other way) to run IsZeor if the function the IsZero retrun
ture then break for_each.
|
'for_each()' does not break: it is intended to apply the given functor
to each element of the sequence. You are looking for a different
algorithm, probably for 'std::find_if()'. Of course, 'std::find_if()'
is intended to use a predicate which does not mutate the elements but
I don't think anything prohibits the predicate to mutate the sequence
elements.
--
<mailto:dietmar_kuehl (AT) yahoo (DOT) com> <http://www.dietmar-kuehl.de/>
<http://www.contendix.com> - Software Development & Consulting
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Thomas Mang Guest
|
Posted: Fri Jan 07, 2005 3:09 pm Post subject: Re: How to use for_each when the mem_fun's fun return "true" |
|
|
"Alberto Barbati" <AlbertoBarbati (AT) libero (DOT) it> schrieb im Newsbeitrag
news:T59Dd.17160$_E5.449777 (AT) twister2 (DOT) libero.it...
| Quote: |
int main( )
{
vector <StoreVals *> v1;
v1.push_back(&StoreVals (5));
WHAT???? Are you crazy? You are inserting a pointer to a temporary
inside a vector! This is very bad! The temporary will be destroyed just
after the ";" so the address you just put in the vector will point to
rubbish. VERY undefined behaviour. In fact, on VC7.1 with release
settings, your program displays "25,25,25,25,25,25," and not
"5,10,15,20,0,25," but it might as well crash and the compiler would
still not be the one to blame.
|
Why does VC7.1 compile this? I mean, does VC7.1 really allow to apply the
built-in operator& to a r-value? [I'm too lazy to look up if a diagnostic is
required, or not. But I think a quality implemention should really not
accept this code.]
Thomas
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Alberto Barbati Guest
|
Posted: Sat Jan 08, 2005 10:50 pm Post subject: Re: How to use for_each when the mem_fun's fun return "true" |
|
|
Thomas Mang wrote:
| Quote: | "Alberto Barbati" <AlbertoBarbati (AT) libero (DOT) it> schrieb im Newsbeitrag
news:T59Dd.17160$_E5.449777 (AT) twister2 (DOT) libero.it...
int main( )
{
vector <StoreVals *> v1;
v1.push_back(&StoreVals (5));
WHAT???? Are you crazy? You are inserting a pointer to a temporary
inside a vector! This is very bad! The temporary will be destroyed just
after the ";" so the address you just put in the vector will point to
rubbish. VERY undefined behaviour. In fact, on VC7.1 with release
settings, your program displays "25,25,25,25,25,25," and not
"5,10,15,20,0,25," but it might as well crash and the compiler would
still not be the one to blame.
Why does VC7.1 compile this? I mean, does VC7.1 really allow to apply the
built-in operator& to a r-value? [I'm too lazy to look up if a diagnostic is
required, or not. But I think a quality implemention should really not
accept this code.]
|
You're right. The code is in fact illegal, according to §5.3.1/2: "The
operand [of operator&] shall be an lvalue". However, VC7.1 happily
compiles it thanks to a "nonstandard extension" (bah!) producing a mere
level 4 warning (double bah!). You have to force ANSI-mode to make the
compiler produce an error.
Alberto
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Dave Harris Guest
|
Posted: Sat Jan 08, 2005 10:53 pm Post subject: Re: How to use for_each when the mem_fun's fun return "true" |
|
|
[email]nospam (AT) nospam (DOT) inva[/email]lid (Thomas Mang) wrote (abridged):
| Quote: | I mean, does VC7.1 really allow to apply the built-in operator& to
a r-value?
|
Yes. Which can be jolly convenient. For example:
void MoveWindow( const CRect *pRect );
void test() {
MoveWindow( &CRect( 0, 0, 100, 100 ) ); // Non-standard.
}
I think it's a shame that temporary objects are second-class citizens in
standard C++.
-- Dave Harris, Nottingham, UK
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Old Wolf Guest
|
Posted: Mon Jan 10, 2005 10:13 am Post subject: Re: How to use for_each when the mem_fun's fun return "true" |
|
|
Dave Harris wrote:
| Quote: | nospam (AT) nospam (DOT) invalid (Thomas Mang) wrote (abridged):
I mean, does VC7.1 really allow to apply the built-in operator& to
a r-value?
Yes. Which can be jolly convenient. For example:
void MoveWindow( const CRect *pRect );
void test() {
MoveWindow( &CRect( 0, 0, 100, 100 ) ); // Non-standard.
}
|
I believe this workaround works:
template<typename T> T const &make_lv(T const &t) { return t; }
MoveWindow( & make_lv( CRect(0, 0, 100, 100) ) );
Another way would be to wrap CRect in a class that overloads
operator& .
Also useful in other situations (although treading
nearer to the fiery pit of undefined behaviour) is:
template<typename T> T &make_lv(T const &t)
{ return const_cast<T &>(t); }
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Thomas Mang Guest
|
Posted: Tue Jan 11, 2005 1:02 pm Post subject: Re: How to use for_each when the mem_fun's fun return "true" |
|
|
"Alberto Barbati" <AlbertoBarbati (AT) libero (DOT) it> schrieb im Newsbeitrag
news:NMDDd.19866$_E5.505607 (AT) twister2 (DOT) libero.it...
| Quote: | Thomas Mang wrote:
"Alberto Barbati" <AlbertoBarbati (AT) libero (DOT) it> schrieb im Newsbeitrag
news:T59Dd.17160$_E5.449777 (AT) twister2 (DOT) libero.it...
int main( )
{
vector <StoreVals *> v1;
v1.push_back(&StoreVals (5));
WHAT???? Are you crazy? You are inserting a pointer to a temporary
inside a vector! This is very bad! The temporary will be destroyed just
after the ";" so the address you just put in the vector will point to
rubbish. VERY undefined behaviour. In fact, on VC7.1 with release
settings, your program displays "25,25,25,25,25,25," and not
"5,10,15,20,0,25," but it might as well crash and the compiler would
still not be the one to blame.
Why does VC7.1 compile this? I mean, does VC7.1 really allow to apply
the
built-in operator& to a r-value? [I'm too lazy to look up if a
diagnostic is
required, or not. But I think a quality implemention should really not
accept this code.]
You're right. The code is in fact illegal, according to §5.3.1/2: "The
operand [of operator&] shall be an lvalue". However, VC7.1 happily
compiles it thanks to a "nonstandard extension" (bah!) producing a mere
level 4 warning (double bah!). You have to force ANSI-mode to make the
compiler produce an error.
|
And I guess then it doesn't compile it's own files (especially API etc.) any
more?
I have played around with VC7.1 some time ago. When level 4 warning were
turned on, I was flooded by all kinds of warnings.
IIRC, one sort of was something like this:
struct t
{
bool is_set() const {return Value;}
int * Value;
};
telling me I am converting a pointer to a bool and performance loss or
something like that. Good analysis. Okay, that warning might be useful
occasionally, but it was more annoying then useful to me.
I wonder because in Exceptional C++ Style, according to Herb Sutter's
homepage one item is "Compile cleanly at high warning levels" (don't know
though what the text says. I don't have the book). But these sort of
warnings are the ones that make you turn warnings off. There were other
examples too. It's especially interesting since one should think Herb Sutter
has influence on VC7.1 and could implement a cleverer and more useful
warning system.
Thomas
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Thomas Mang Guest
|
Posted: Tue Jan 11, 2005 1:04 pm Post subject: Re: How to use for_each when the mem_fun's fun return "true" |
|
|
"Dave Harris" <brangdon (AT) cix (DOT) co.uk> schrieb im Newsbeitrag
news:memo.20050107203806.2004A (AT) brangdon (DOT) m...
| Quote: | nospam (AT) nospam (DOT) invalid (Thomas Mang) wrote (abridged):
I mean, does VC7.1 really allow to apply the built-in operator& to
a r-value?
Yes. Which can be jolly convenient. For example:
void MoveWindow( const CRect *pRect );
void test() {
MoveWindow( &CRect( 0, 0, 100, 100 ) ); // Non-standard.
}
|
And why not take a reference to const as parameter?
[Okay, I guess this way one can pass the address of a temporary to a
function taking pointer to non-const and modify the temporary this way. Or
circumvent an accessible copy constructor. Don't know though if this is
good, or bad, or neutral.]
| Quote: |
I think it's a shame that temporary objects are second-class citizens in
standard C++.
|
They are worse than that. Second class citizens are already the floating
types (you cannot have them as non-type template parameters, no in-class
initialized static data members, and you better don't create objects of
them - not even const - in headers, because e.g. if inline functions with
external linkage reference them, you can easily get violation of ODR.
Something like 'double const Pi(3.1415927)' in a header is invitation to UB.
Still I wonder how much code does this.)
Thomas
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Dave Harris Guest
|
Posted: Wed Jan 12, 2005 8:59 pm Post subject: Re: How to use for_each when the mem_fun's fun return "true" |
|
|
[email]nospam (AT) nospam (DOT) inva[/email]lid (Thomas Mang) wrote (abridged):
| Quote: | And why not take a reference to const as parameter?
|
In this case, because the API is intended to be compatible with C, and C
doesn't have references. In other cases, because NULL is a permitted
argument.
The very fact that references are allowed here argues that pointers should
be too, in my view.
-- Dave Harris, Nottingham, UK
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Allan W Guest
|
Posted: Wed Jan 12, 2005 9:01 pm Post subject: Re: How to use for_each when the mem_fun's fun return "true" |
|
|
I can agree with Alberto Barbati that the name IsZero (which is what
the OP apparently meant) is a misnomer, because it has non-debug
side-effects. But mutating? Which part of
.. bool IsZeor(){cout<
changes anything in the container?
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
MS Guest
|
Posted: Fri Feb 04, 2005 11:23 am Post subject: Re: How to use for_each when the mem_fun's fun return "true" |
|
|
| Quote: |
And I guess then it doesn't compile it's own files (especially API etc.) any
more?
I have played around with VC7.1 some time ago. When level 4 warning were
turned on, I was flooded by all kinds of warnings.
IIRC, one sort of was something like this:
struct t
{
bool is_set() const {return Value;}
int * Value;
};
telling me I am converting a pointer to a bool and performance loss or
something like that. Good analysis. Okay, that warning might be useful
occasionally, but it was more annoying then useful to me.
I wonder because in Exceptional C++ Style, according to Herb Sutter's
|
In this instance just change the code to
bool is_set() const { return (Value != 0); }
would shut that warning up (under vc). The only warning I have found I
cannot silence without using a compiler specific pragma is when passing
this to an object's constructor in an initialiser list and in this case
its not necceasrily a bad thing as it forces me to document that doing
so in those instances is safe. With third party libraries that do not
compile at warning level 4 it simple enough to use compiler specific
pragmas to temporarily reduce the warning level and restore it around
those headers , again forcing you to document why you are doing this.
Herb's advice is good, you just need to put some more effort into
finding ways to supress the few instances of false positives;)
martin
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
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
|
|