Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

function objects versus function pointers

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() );  

Question :

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

Question

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.

like image 335
kumar_m_kiran Avatar asked Jun 09 '10 00:06

kumar_m_kiran


2 Answers

Question 1:

PopLess() must be resolved into something like PopLess > 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).

like image 176
utnapistim Avatar answered Sep 22 '22 09:09

utnapistim


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.

like image 37
Jacob Avatar answered Sep 18 '22 09:09

Jacob