STL not only enables us to write complex code more easily and quickly, but also makes the written code both standard and highly optimized.
Std: vector <std: string> names;
//...
Std: sort (names. begin (), names. end ());
Another elegance of STL is that it is highly configurable. In the above Code, the string element in the vector is sorted using the <) operator of the string, but in other cases, there may not always be a less than operator available, in addition, you do not want to sort data in ascending order.
Class State
{
Public:
//...
Int population () const;
Float aveTempF () const;
//...
};
The State class is used to represent a federated State. It is neither smaller than the operator nor intended to implement one State for it, because "one State is smaller than another State" cannot tell what it means. Fortunately, STL generally allows us to specify an alternative operation similar to the less-than-like operator. This operation is called a "Comparator" because it is used to compare two values:
Inline bool popLess (const State & a, const State & B)
{
Return a. population () <B. population ();
}
With a comparator for State, you can use it for sorting:
State aUnion [50];
//...
Std: sort (aUnion, aUnion + 50, popLess); // sort by population
Here we pass a pointer to the popLess function as the comparator (the function name degrades to a pointer ). Because popLess is passed as a function pointer, it cannot be inline in sort. If you want to get a quick sorting operation, this can only be a pity.
If you use a function object as the comparator, the situation will be much better:
Struct PopLess: public std: binary_function <State, State, bool>
{
Bool operator () (const State & a, const State & B) const
{
Return a. population () <B. population ();
}
};
The PopLess type is a typical example of a properly constructed STL function object.
First, it is a function object. It reloads the function call operator, so it can be called using the syntax of common function call. This is important because STL generic algorithms such as sort are written in this way: function pointers and function objects can be used to instantiate them, as long as the two can be called using the typical function call syntax. A function object with an overloaded operator () can fully meet this syntax requirement.
Secondly, it is derived from the standard binary_function base class. This mechanism allows STL implementation of other parts to ask questions about the function object compiler. In this example, the PopLess type derived from binary_function allows us to find out the parameters and return value types of function objects. However, we have not used this capability here, but we can bet that someone needs it, and we hope our PopLess type can be used by others.
Third, this function object has no data members, no virtual functions, no declarative constructors and destructor displayed, and the implementation of operator () is inline. Function objects used as STL comparator are generally very small. Simple and fast. Of course, you can design an STL function object with a heavy implementation, but this is usually not wise. When used in collaboration with STL, another reason for avoiding (or minimizing) using data members in function objects is that STL implementation may generate several copies for a function object, it is also assumed that all these copies are consistent. To ensure that all the copies of an object are consistent, the simplest way is not to let the object carry any data members.
Now we can use this function object to sort the aUnion:
Std: sort (aUnion, aUnion + 50, PopLess (); // sort by population
Note the parentheses following the PopLess in this sort call. PopLess is a type, but we must input an object of this type as a function parameter. By appending a pair of parentheses after a PopLess type name, a temporary PopLess object with no name is created, this object only exists during the function call period (this unnamed object is the "anonymous temporary object" in the total region "). You can also declare and pass in a named object:
PopLess comp;
Std: sort (aUnion, aUnion + 50, comp); // sort by population
However, it is easier to pass in an anonymous temporary object, more suitable for habits, and fewer keys.
Another advantage of using a function object as a comparator is that a comparison operation will be processed in inline mode, while a function pointer cannot be used in inline mode. The reason is that when an sort function template is instantiated, the compiler knows that the type of the comparator is PopLess, so that it knows that PopLess: operator () will be called, and then enables it to inline the function.
In STL, another common purpose of a function object is to use it as a scalar. Implicit is an operation that asks true/false questions about a single object (you can regard a comparator as a binary scalar ).
Struct IsWarm: public std: unary_function <State, bool>
{
Bool operator () (const State & a) const
{
Return a. aveTempF ()> 60;
}
};
The STL primitive design knows that the policy is consistent with that of the STL comparator. The only exception is that the former is a mona1 function, not a binary function. Starting from the result of our previous sorted State, we can easily find a State with a warm climate and a small number of people:
State * warmandsparse = find_if (aUnion, aUnion + 50, IsWarm ());