First, how do you find the code below, I mean if you review it, please? |
So constructively teaching, as it's the author's bible:
3.4.3 Function Objects
One particularly useful kind of template is the function object (sometimes called a functor), which
is used to define objects that can be called like functions. For example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
|
template<typename T>
class Less_than {
const T val; //
value to compare against
public:
Less_than(const T& v) :val(v) { }
bool operator()(const T& x) const { return x<val; } //
call operator
};
The function called operator() implements the ‘‘function call,’’ ‘‘call,’’ or ‘‘application’’ operator ().
We can define named variables of type Less_than for some argument type:
Less_than<int> lti {42}; //
lti(i) will compare i to 42 using < (i<42)
Less_than<string> lts {"Backus"}; //
lts(s) will compare s to "Backus" using < (s<"Backus")
We can call such an object, just as we call a function:
void fct(int n, const string & s)
{
bool b1 = lti(n); //
true if n<42
bool b2 = lts(s); //
true if s<"Backus"
//
...
}
Such function objects are widely used as arguments to algorithms. For example, we can count the
occurrences of values for which a predicate returns true:
template<typename C, typename P>
int count(const C& c, P pred)
{
int cnt = 0;
for (const auto& x : c)
if (pred(x))
++cnt;
return cnt;
}
A predicate is something that we can invoke to return true or false. For example:
void f(const Vector<int>& vec, const list<string>& lst, int x, const string& s)
{
cout << "number of values less than " << x
<< ": " << count(vec,Less_than<int>{x})
<< '\n';
cout << "number of values less than " << s
<< ": " << count(lst,Less_than<string>{s})
<< '\n';
}
| |
its used to specify the meaning of key operations of a general algorithm (such as Less_than for count()) are often referred to as policy objects.
We have to define Less_than separately from its use. That could be seen as inconvenient. Consequently, there is a notation for implicitly generating function objects
Such function objects are widely used as arguments to algorithms.
We can count the occurrences of values for which a predicate returns true:
1 2 3 4 5 6 7 8 9
|
void f(const Vector<int>& vec, const list<string>& lst, int x, const string& s)
{
cout << "number of values less than " << x
<< ": " << count(vec,[&](int a){ return a<x; })
<< '\n';
cout << "number of values less than " << s
<< ": " << count(lst,[&](const string& a){ return a<s; })
<< '\n';
}
| |
The notation [&](int a){ return a<x; } is called a lambda expression (§11.4). It generates a function object exactly like Less_than<int>{x}.
The [&] is a capture list specifying that local names used
(such as x) will be passed by reference. Had we wanted to ‘‘capture’’ only x, we could have said so: [&x].
Had we wanted to give the generated object a copy of x, we could have said so: [x]. Capture nothing is [], capture all local names used by reference is [&], and capture all local names used by value is [=]... Ch. 3 p. 81