Overview of STL Function Objects
• Function Object (also known as a Functor)
– STL Function Objects support function call syntax
• E.g., a class that declares and defines operator()
• E.g., by being a function pointer
– GoF Command pattern may be applied to classes and
structs (user-defined types)
• Encapsulate a function call as an object
• Some or all of these can be member variables
– Target object reference, function to invoke, arguments
• Generic programming allows diverse types
– A function pointer (example from Lippman, LaJoie, Moo)
bool (*pf) (const string &, const & string) // function pointer
bool *pf (const string &, const & string) // function named pf
– An instance of a class providing operator()
CSE 332: C++ STL function objects
Function Objects Extend STL Algorithms
• Make the algorithms even more general
• Parameterize policy
– E.g., the order produced by a sorting algorithm
• Each functor does a single, specific operation
– Often implemented as small classes or structs
– Often has only one public member function, operator()
• Functors may also have member variables
– Arguments not stored may be supplied at point of call
– Member variables can parameterize the operation
– E.g., the value k for a +k functor
– E.g., arguments for an invocation on a remote object
CSE 332: C++ STL function objects
Examples of Function Object Usage
struct GT_magnitude
int main (int, char **) {
: public
binary_function<double, vector<double> u,v;
double, for (double d = 0.0;
bool> { d < 10.1; d += 1.0){
bool operator()
u.push_back (d);
(double x, double y) {
return v.push_back (d);
fabs(y) < fabs(x); }
} sort (u.begin(), u.end(),
}; GT_magnitude());
struct LT_magnitude
sort (v.begin(), v.end(),
: public
binary_function<double, LT_magnitude());
double, ostream_iterator<double>
bool> { o (cout, “ ”));
bool operator()
copy (u.begin(), u.end(), o);
(double x, double y) {
return copy (v.begin(), v.end(), o);
fabs(x) < fabs(y); return 0;
} }
};
CSE 332: C++ STL function objects
Function Object Concepts
• Basic Function Object Concepts
– Generator
– Unary Function
– Binary Function
• Adaptable Function Objects (turn functions into functors)
– Adaptable Generator
– Adaptable Unary Function
– Adaptable Binary Function
• Predicates (return a boolean result)
– Predicate
– Binary Predicate
– Adaptable Predicate
– Adaptable Binary Predicate
– Strict Weak Ordering
• Specialized Concepts
– Random Number Generator
– Hash Function
CSE 332: C++ STL function objects
Function Object Concept Hierarchy
Assignable is-ref
ined-b
y
Generator
Binary
Unary Function
Adaptable Function
Generator
Adaptable Binary
Random Binary Predicate
Adaptable Predicate Number Function
Unary Generator
Function
Adaptable Hash Adaptable Strict
Predicate Function Binary Weak
Predicate Ordering
Basic Function Object Predicate
Adaptable Function Object Specialized
CSE 332: C++ STL function objects
Assignable Concept
• Does not refine any other STL concept
• Valid Expressions
– Copy Constructor
X(x); X x(y); X x = y;
– Assignment
x = y;
• Models of Assignable
– Almost every non-const C++ built-in type
– Here, all Basic Function Object concepts
• Generator, Unary Function, Binary Function
• And the concepts that specialize them
CSE 332: C++ STL function objects
Generator Concept
• Refines Assignable
• Abstracts 0-ary functions (take no arguments)
• Valid Expressions
– Function call signature with no arguments
f()
• Semantics
– Returns some value of type Result
– Different invocations may return different values
• Or, can represent a constant as a 0-ary functor
– Invocation may change the function object’s internal state
• So, operator() need not be a const member function
CSE 332: C++ STL function objects
Generator Example
• Goal: fill a vector with random numbers
• Generic generate algorithm
– Fills in a range given in its 1st and 2nd arguments
– applies Generator Concept to its 3rd argument
• Here, the functor is simply a function pointer
– To the C library’s (0-ary) rand() function
vector<int> v(100);
generate(v.begin(), v.end(), rand);
CSE 332: C++ STL function objects
Unary Function
• Also a refinement of Assignable
• Valid Expression
– Function call signature with one argument
f(x)
– Semantics
• May ignore or use single argument
• Similar return, const semantics to generator
• Example - Unary Sine Functor
struct sine
: public unary_function<double,double> {
double operator()(double x) const
{
return sin(x);
}
};
CSE 332: C++ STL function objects
Binary Function
• Also a refinement of Assignable
• Valid Expression
– Function call signature with two arguments
f(x,y)
– Semantics
• May use or ignore either or both of its arguments
• Similar const and return semantics to Unary Function
• Example - Exponentiation Functor
struct exponentiate
: public binary_function<double,double,double> {
double operator()(double x, double y) const
{
return pow(x,y);
}
};
CSE 332: C++ STL function objects
Adaptable Function Objects
• Allow functors to be used with Function Object Adaptors
• Associated types – of argument(s), and especially return value
• How to access these associated types ?
– Define Adaptable Function Object Concepts
• Adaptable Generator
F1::result_type
• Adaptable Unary Function
F2::argument_type F2::result_type
• Adaptable Binary Function
F3::first_argument_type
F3::second_argument_type F3::result_type
• Models
– Functions like Result(*f)(Arg) are not models of these concepts
– Helper adapters make Adaptable Function Objects from these functions
– For example ptr_fun(f) is a model of Adaptable Unary Function
CSE 332: C++ STL function objects
Adaptable Function Object Example
• Each value in v2 will be 3.0 larger than the
corresponding element in v1
const int N = 1000;
vector<double> v1(N);
vector<double> v2(N);
// random values
generate(v1.begin(), v1.end(), rand);
transform(v1.begin(), v1.end(),
v2.begin(),
bind1st(plus<double>(), 3.0));
Adaptable Function Object
Function Object Adapter (we’ll cover these in a bit)
CSE 332: C++ STL function objects
Predicate Concepts
• Predicate
– Refinement of Unary Function
– Return type must be convertible to bool
• Adaptable Predicate
– Refinement of Predicate, Adaptable Unary Function
– Adds typedefs for argument, return types
• Binary Predicate
– Refinement of Binary Function
– Return type again must be convertible to bool
• Adaptable Binary Predicate
– Refinement of Binary Predicate, Adaptable Binary Function
– Adds typedefs for the 2 arguments, return types
• Strict Weak Ordering
– Refinement of Binary Predicate (for comparison operations)
– Similar semantics to operator< but with type constraints
CSE 332: C++ STL function objects
Random Number Generator
• Refinement of Unary Function
– Unfortunately name is similar to Generator (0-ary)
• Valid Expression
– Function call
f(N), where N is a positive integer
• Semantics
– Returns some value of type Result
– Different invocations may return different values
– Normal pseudo-random distribution
• If function f is called many times with the same argument N then
• Each value in range [0,N) will appear ~ equal number of times
CSE 332: C++ STL function objects
Hash Function
• Refinement of Unary Function
– Return type must be size_t
• Valid Expression
– Function call
f(x)
• Semantics
– Map from argument to a size_t result
– Equivalent arguments must yield same result
– Used by Hashed Associative Containers
CSE 332: C++ STL function objects
Function Object Adaptors
• Adaptors transform one interface to another
– I.e., they implement the Adapter pattern
• Function Object Adaptors
– Perform function composition and binding
– Allows fewer ad hoc function objects
– Allows you to build functions as graphs (especially
chains and trees) of other functions
CSE 332: C++ STL function objects
Composition and Binding with Function Objects
• Function Composition
– f and g are both Adaptable Unary Functions
– g return type is convertible to f argument type
– (f ◦ g)(x) which is f(g(x)) can be written using
unary_compose<f,g> or compose1(f,g)
• Function Binding
– Adaptable Binary Function to Adaptable Unary Function
– Bind first argument using binder1st<BinaryFun>
• Where f is an object of type binder1st<F>
• f(x) F(c,x) where c is constant
– Bind second argument using binder2nd<BinaryFun>
• Where f is an object of type binder2nd<F>
• f(x) F(x,c) where c is constant
CSE 332: C++ STL function objects
Example of Function Composition
• Calculate negative of sine of angles in degrees
• Performed as a sequence of three operations
– Conversion of degrees to radians
– Calculation of sine
– Negation
vector<double> angles;
// ... push in some radian values ...
vector<double> sines;
const double pi = 3.14159265358979323846;
transform(angles.begin(), angles.end(), sines.begin(),
compose1(negate<double>(),
compose1(ptr_fun(sin),
bind2nd(multiplies<double>(),
pi / 180.0))));
CSE 332: C++ STL function objects
Example of Explicit Call Chains
• Carry out operations in some specified order
template <class R, class List>
class Chain {
Fun2& operator()(const Fun1<R, List>& fun1,
const Fun2<R, List>& fun2)
{
fun1();
return fun2();
}
};
CSE 332: C++ STL function objects
Member Function Adaptors
• Allows use of member functions as Function Objects
• Similar adaptors available for non-member functions
• Take an X* or X& argument and call one of the X
object’s member functions through that argument
• If the member function is virtual, call is polymorphic
• Three variations
– Argument type X* vs. X&
– Member Function takes zero vs. one argument
– Encapsulates non-const vs. const member function
CSE 332: C++ STL function objects
Member Function Adaptor Example
struct B { virtual void print() = 0; };
struct D1 : public B {
void print() { cout << "I'm a D1" << endl; } };
struct D2 : public B {
void print() { cout << "I'm a D2" << endl; } };
int main(int, char **) {
vector<B*> v;
v.push_back(new D1); v.push_back(new D2);
v.push_back(new D2); v.push_back(new D1);
for_each(v.begin(), v.end(), mem_fun(& B::print));
return 0;
}
CSE 332: C++ STL function objects
Concluding Remarks
• Passing parameters to Functors
– Can do by value or by reference
– Same kinds of aliasing issues, etc. as with any other object
• Watch performance with many small function objects
– Watch out especially for creation, destruction overhead
– May want to inline functors constructors, destructors
– Put function objects on stack instead of heap
• Function objects are a powerful, general mechanism
– Reduces programming complexity, increases reuse
– Several new uses of generic programming
– Could go farther with parameterization than just algorithms
• Use functors to make smarter iterators and containers
CSE 332: C++ STL function objects