I have two questions related to function objects and function pointers,
Question : 1
When I read the different uses sort
algorithm of STL, I see that the third parameter can be a function objects, below is an example
class State {
public:
//...
int population() const;
float aveTempF() const;
//...
};
struct PopLess : public std::binary_function<State,State,bool> {
bool operator ()( const State &a, const State &b ) const
{ return popLess( a, b ); }
};
sort( union, union+50, PopLess() );
Now, How does the statement, sort(union, union+50,PopLess())
work? PopLess()
must be resolved into something like PopLess tempObject.operator()
which would be same as executing the operator ()
function on a temporary object. I see this as, passing the return value of overloaded operation i.e bool
(as in my example) to sort
algorithm.
So then, How does sort function resolve the third parameter in this case?
Question : 2
Do we derive any particular advantage of using function objects versus function pointer? If we use below function pointer will it derive any disavantage?
inline bool popLess( const State &a, const State &b )
{ return a.population() < b.population(); }
std::sort( union, union+50, popLess ); // sort by population
PS : Both the above references(including example) are from book "C++ Common Knowledge: Essential Intermediate Programming" by "Stephen C. Dewhurst".
I was unable to decode the topic content, thus have posted for help.
Thanks in advance for your help.
Question 1:
PopLess()
must be resolved into something likePopLess > tempObject.operator()
which would be same as executing the operator () function on a temporary object.
It's not [expanded as you said]. PopLess()
is actually the call to the implicit PopLess::PopLess()
constructor. This code creates a temporary object and passes it to the 3rd parameter in the function call.
Question : 2
Do we derive any particular advantage of using function objects versus function pointer?
Not in this case. Here your PopLess object is stateless. You can create functors (function objects) that have internal state.
Example:
struct ensure_min
{
int value;
ensure_min(int val) : value(val) {}
int operator()(const int& i)
{
return std::max(value, i);
}
}
std::vector<int> values;
values.push_back(-1);
values.push_back(0);
values.push_back(1);
values.push_back(2);
values.push_back(3);
std::transform(values.begin(), values.end(),
std::ostream_iterator<int>(std::cout, "\n"), ensure_min(1));
This code will output all the numbers in the sequence, ensuring all the numbers in the output have a minimal value of 1 (the output is either 1 - if the original number was any less - or the original number if the original number was greater than or equal to 1).
Q1: PopLess()
constructs an object of type PopLess
and sort
then uses this object to sort the elements in the range using the operator ()
.
Looking at the for_each
function might be easier, it could be implemented like this:
template <typename IterT, typename Function>
Function for_each( IterT first, IterT last, Function f ) {
for( ; first != last; ++first )
f(*first);
return f;
}
So basically for_each
and sort
, and functions using function objects, simply take an instance of your function object and call its operator ()
.
Q2: A compiler might be able to optimize away the function call by inlining when you are using a function object rather than a function pointer, this might not be as straight forward for the compiler to do with the function pointer. Also, a function object can have state.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With