TITLE: function objects (Source: comp.lang.c++.moderated, 26 Oct 2000) NICK_NW: nick_nw@my-deja.com > Ive recently switched jobs from a C programmer to a C++ programmer. > Im trying to learn all the ins and outs of C++, but have to admit im > having difficulty with functors. > I know how to use them, etc., but im still not convinced of how > useful they would be. > Have any of you good examples of when you have used functors? Im > not after source code, just situations / problems that youve > encountered that the only solution is to use functors. Or maybe > just when functors are better used. KANZE: James Kanze First, about the only time a functor is useful is when you would take the address of a function. Functors can have state; pointers to functions can't. Imagine a function integrate. In classical C, this would probably be written: double integrate( double from , double to , double (*f)( double ) ) ; In C++, the pointer to a function would typically be replaced by a reference to a functor, resolved either by inheritance or templates, e.g.: class Function { public: virtual ~Function() {} virtual double operator()( double ) const = 0 ; } ; double integrate( double from , double to , Function const& f ) ; Now suppose I want to integrate a series of linear expressions, of the form a*x+b. In C, I'd either have to write a separate function for each expression, or place a and b in global variables somewhere where the function could find them. In C++, on the other hand, I could write: class LinearExpression { public: LinearExpression( double anA , double aB ) : a( anA ) , b( aB ) {} virtual double operator()( double x ) const { return a * x + b ; } private: double a ; double b ; } ; And then pass different instances of the functor to the function. (I've used inheritance here, as I find it easier to understand and more flexible, but in this case, the choice between inheritance and templates is rather arbitrary -- both will work. If the integrate function is large, and called with many different types, templates will cause code bloat. And if the functor is typically very simple, as it is here, inheritance will cause higher run-time overhead in most compilers.) The situation is even more interesting when the function itself modifies the state of the functor, although such functors are not in general usable with the standard library (because the standard library makes arbitrary copies of the functor). In most such cases, you'll probably want to use a handle to the state in the functor, i.e.: class Average { public: Average() : data( new Data ) {} void operator()( double value ) const { ++ data.count ; data.total += value ; } double value() const { return data.total / data.count ; } private: struct Data : public RefCntObj { double total ; int count ; Data() : total( 0.0 ) , count( 0 ) {} } ; RefCntPtr< Data > data ; } ; You can then write things like: std::for_each( v.begin() , v.end() , Average() ).value() A one liner that returns the average of all of the values in an array. Not yet APL, but getting there:-). (Note that without the handle, this is *not* guaranteed.) WITTLICH: Klaus Wittlich [Klaus_Wittlich@sae.de] If you use a function that is controlled by global variables you can not use it in a multi - thread environment simultaneosuly by more than one thread if the threads need different function controls by the global values. If you encapsulate these global variables in a function object the problem is solved in most cases, each thread can have a copy of its own "global variables" for controlling the behaviour of the function. _______________________________________________ cpptips mailing list http://cpptips.hyperformix.com