Upload
claude-thomas
View
214
Download
2
Embed Size (px)
Citation preview
CS212: Object Oriented Analysis and Design
Lecture 28: Functors
Recap of Lecture 27
• STL Algorithms
• Accumulate
• Reordering algorithms
• Searching algorithm
• Removing algorithm
Outline of Lecture 28
• Adapters
• Predicate functions
• Function Objects
Iterator Adaptors
0 1 2 3 4 5 6
0 0 0 0 0 0 0
Source
Target
0 1 2 3 4 5 6
0 1 2 3 4 5 6
Source
Target
Before copy
After copy
copy(start, stop, result)
Iterator Adaptors
• Iterator adaptors are defined in the <iterator> header
• They are objects that act like iterators
• Don't actually point to elements of a container
• e.g. ostream_iterator
A closer look at ostream_iterator
• They are parameterized
• We passed it two pieces of information
1. A stream to write to, in this case cout
2. A separator string
• Demonstration (Iter_Adapt.cpp)
ostream_iterator<int> myItr(cout, " ");
vector<int>::iterator it;
ostream_iterator
• Iterator adaptors are iterators, and so they can be used in conjunction with the STL algorithms
• Supply an iterator adaptor instead to “trick” the algorithm
• Performing some complex task when it believes it's just writing values to a range
copy(myVector.begin(), myVector.end(), ostream_iterator<int>(cout, " "));
Common Iterator adapter
Name Example
back_insert_iteratorback_insert_iterator<vector<int> >
itr(myVector);
front_insert_iteratorfront_insert_iterator<deque<int> >
itr(myIntDeque);
insert_iteratorinsert_iterator< set<int> > itr( mySet,
mySet.begin());
ostream_iterator ostream_iterator<double> itr( myStream, "\n");
istream_iterator istream_iterator<int> itr(cin);
A Word on Compatibility
• STL implementations are uniform
• C++ code that works on one compiler should work on any other compile
• Unfortunately, this is not the case
string ConvertToLowerCase(string text) {
transform(text.begin(), text.end(),
text.begin(), tolower); return text; }
Predicate functions
• Many of the STL generic algorithms take a functional argument
template <class InputIterator, class T> T accumulate (InputIterator first, InputIterator last, T init);
template< class InputIterator, class T, class BinaryOperation >T accumulate( InputIt first, InputIt last, T init, BinaryOperation op );
Second version uses a given binary function
The signature of the function should be equivalent to the following: Ret fun(const Type1 &a, const Type2 &b);
Demonstration (AccumCustom.cpp, SortCustom.cpp)
Common binary predicates
equal_to(){
if (arg1 == arg2) return TRUE;
else return FALSE;
}
not_equal_to()
greater()
less()
greater_equal()
less_equal()
logical_and()
logical_or()
Common arithmetic functions
• plus(){ return ( arg1 + arg2); }
• minus(){ return ( arg1 - arg2 ); }
• multiplies(){ return ( arg1 * arg2 ); }
• divides(){ return ( arg1 / arg2 ); }
• modulus(){ return ( arg1 % arg2 ); }
Function Objects
string mystr[] = {“Me”,”You”,”He”,”She”,”You”,”They”};
int mycount = count (mystr, myints+6, “You”);
The function uses operator == to compare the individual elements to val.
Count the number of strings that have length greater than 3
int numEvens = count_if(myVector.begin(), myVector.end(), LengthIsLessThanThree);
bool LengthIsLessThanThree(const string& str) { return str.length() < 3; }
Alternative design
• A function has access the following information:
• Its local variables.
• Its parameters.
• Global variables.
• This is not an optimal solution
• It is error-prone, It is not scalable, It uses global variables
bool LengthIsLessThanThree(const string& str, size_t length) { return str.length() < length;} Should be unary
Functors to rescue
• Issue: Unary function does not have access to enough information
• Intension: A unary function to act like a binary function without taking an extra parameter
• A functor (or function object) is an C++ class that acts like a function
• Can be accessed like objects, but behaves like functions
MyClass myFunctor;
cout << myFunctor(137) << endl;
More on functor signature
• Create an object that overloads the function call operator, operator ()
• It is a function called operator (), not a function called operator that takes no parameters
• Defining a function that gets called if we invoke the object like a function
cout << myFunctor(137) << endl;
is equivalent to
cout << myFunctor.operator()(137) << endl;
The operator()
• Return an object of any type (or even void)
• Can accept any number of parameters
class MyFunctor { public: void operator() (const string& str) const
{ cout << str << endl; } };
Functions vs Functors
• A functor's function call operator is a member function
• A raw C++ function is a free function
A function has access to
• Its local variables.
• Its parameters.
• Global variables.
A functor has access to
• Its local variables.
• Its parameters.
• Global variables.
• Class data members.
count_if revisited
int numEvens = count_if(myVector.begin(), myVector.end(), LengthIsLessThanThree);
class ShorterThan { private:
const size_t length; public:
ShorterThan(size_t maxLength) : length(maxLength) {}bool operator() (const string& str) const {
return str.length() < length; }};
count_if(myVector.begin(), myVector.end(), ShorterThan(length));
Function with local state
• Those local variables can be very useful
Suppose you wanted to look at a container of XY coordinates and find the one closest to some point P.
template <class ForwardIterator> ForwardIterator min_element (ForwardIterator first, ForwardIterator last, Compare comp );
Thank youNext Lecture: Functors