220 likes | 383 Views
Function Objects Extend STL Algorithms. Make the algorithms even more generalParameterize policyE.g., the order produced by a sorting algorithmEach functor does a single, specific operationOften implemented as small classes or structsOften has only one public member function, operator() Functo
E N D
1. 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()
2. 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
3. Examples of Function Object Usage struct GT_magnitude
: public binary_function<double,
double,
bool> {
bool operator()
(double x, double y) {
return
fabs(y) < fabs(x);
}
};
struct LT_magnitude
: public binary_function<double,
double,
bool> {
bool operator()
(double x, double y) {
return
fabs(x) < fabs(y);
}
};
4. 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
5. Function Object Concept Hierarchy
6. 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
7. 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
8. 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);
9. 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);
}
};
10. 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);
}
};
11. 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
12. 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));
13. 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
14. 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
15. 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
16. 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
17. 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
18.
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))));
19.
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();
}
};
20. 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
21. 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;
}
22. 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