Function objects with state

D

Dave

Hello all,

When working with the STL, under what circumstances may I use a function
object that modifies its internal state from one call to the next? I know
this can be done with for_each<>(). I know it cannot be done if the function
object happens to be a predicate.

Is there a general rule that says when a function object can or cannot
modify state?

Thanks,
Dave
 
M

Mark P

Dave said:
Hello all,

When working with the STL, under what circumstances may I use a function
object that modifies its internal state from one call to the next? I know
this can be done with for_each<>(). I know it cannot be done if the function
object happens to be a predicate.

Is there a general rule that says when a function object can or cannot
modify state?

Thanks,
Dave

I'm not an expert, but... I don't know of any express prohibition
against a function with internal state, even if it is a predicate.
Indeed this is one of the benefits of using a function object.

Of course, you have to avoid doing silly things like changing the
comparison value of objects while stored in a sorted container. In my
own codes, I've often found it more useful to have a function object
that contains a pointer to some external data so that the external data
can be modified be an external element. (Hard to do otherwise since the
container will have its own copy of the function.)

HTH,
Mark
 
D

Dave

Mark P said:
I'm not an expert, but... I don't know of any express prohibition
against a function with internal state, even if it is a predicate.
Indeed this is one of the benefits of using a function object.

Of course, you have to avoid doing silly things like changing the
comparison value of objects while stored in a sorted container. In my
own codes, I've often found it more useful to have a function object
that contains a pointer to some external data so that the external data
can be modified be an external element. (Hard to do otherwise since the
container will have its own copy of the function.)

HTH,
Mark

Oh, I agree that *having* internal state is not bad in any case. It's just
that in some cases, that state should never be *changed*. A case in point
would be a predicate. In other cases, it is OK to let the functor change its
state from one call to the next.
 
K

Kai-Uwe Bux

Dave said:
Hello all,

When working with the STL, under what circumstances may I use a function
object that modifies its internal state from one call to the next? I know
this can be done with for_each<>(). I know it cannot be done if the
function object happens to be a predicate.

I do not understand why it *cannot be done* if the function object is a
predicate. Consider:

#include <cstdlib>
#include <algorithm>
#include <vector>
#include <iostream>
#include <iterator>

struct RandomPredicate {

RandomPredicate ( unsigned long _seed ) {
std::srand( _seed );
}

bool operator() ( int ) {
return( std::rand() < ( RAND_MAX >> 2 ) );
}

}; // RandomPredicate

int main ( void ) {
RandomPredicate P ( 1234 );

std::vector< int > i_vect;
for ( unsigned i = 0; i < 20; ++i ) {
i_vect.push_back( i );
}
std::eek:stream_iterator<int> o_iter ( std::cout, " " );
std::remove_copy_if( i_vect.begin(), i_vect.end(), o_iter, P );
}

Here a predicate object is used to make a random selection. Note that
std::remove_copy_if does not assume that the calling the same predicate
twice on the same object will yield identical results. At least, I did not
see that assumption stated in the standard.


Or consider this:

#include <cstdlib>
#include <algorithm>
#include <vector>
#include <iostream>
#include <iterator>

template < typename T >
struct CountingCompare {

// NOTE: [static to avoid hassle]
/*
std::sort receives a copy of the function object. To ensure that
we see the counter afterwards, we either have to use a pointer
(hassle) or a static variable (quick hack).
*/
static unsigned long count;

bool operator() ( T const & a,
T const & b ) const {
++ count;
return( a < b );
}

}; // CountingCompare

template < typename T >
unsigned long CountingCompare<T>::count = 0;

int main ( void ) {
CountingCompare<int> int_comp;
std::vector<int> i_vect;
for ( unsigned i = 0; i < 2000; ++i ) {
i_vect.push_back( i );
}
std::random_shuffle( i_vect.begin(), i_vect.end() );
std::sort( i_vect.begin(), i_vect.end(), int_comp );
std::cout<< "Sort needed " << int_comp.count << " comparisons\n";
}

Here, a statefull binary predicate is used to count how many comparisons
are done by std::sort. This works since the object still behaves like
an order relation. That is has a state, which changes, is irrelevant to the
algorithm.

Is there a general rule that says when a function object can or cannot
modify state?

No, those rules have to be stated for each algorithm / method seperately.



Best

Kai-Uwe Bux
 

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
474,203
Messages
2,571,059
Members
47,668
Latest member
SamiraShac

Latest Threads

Top