Thread: Why do we need "Functor"?

  1. #1
    Registered User
    Join Date
    Apr 2007
    Posts
    284

    Why do we need "Functor"?

    Why do we need "Functor"? Can't template or function pointer work?
    Could anybody give me examples that a functor is better than a template/functor pointer? Thanks

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I think this is a typical case of "there are multiple methods that will solve the same problem" - and which is "best" depends partly on your personal preferences, along with "what exactly you are trying to solve".

    In other words we don't HAVE TO HAVE functors - but used correctly, they may help to solve some problems in a simpler way.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by meili100 View Post
    Why do we need "Functor"? Can't template or function pointer work?
    Could anybody give me examples that a functor is better than a template/functor pointer? Thanks
    A functor can carry parametrized information with it. For instance, this functor:

    Code:
    class multiply_by
    {
    public:
        multiply_by(double val_p)
            : val(val_p)
        { }
    
        double operator()(double x)
        {
            return x * val;
        }
    
    private:
        double val;
    };
    Example usage:

    Code:
    multiply_by times_three(3.0);
    double x = 15.0;
    double result = times_three(x);
    Let's see you do that without a functor and without passing a second parameter to times_three().

  4. #4
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Quote Originally Posted by matsp View Post
    I think this is a typical case of "there are multiple methods that will solve the same problem" - and which is "best" depends partly on your personal preferences, along with "what exactly you are trying to solve".
    Or being able to use the same method to do things instead of having to write a new method for them all the time. Like in this example, where we can sort by a person's name, or do a lot of other things, like, find someone. It might not even matter what kind of person he or she is. Functors encapsulate these types of ideas better than a "real" function because you can control they're lifetime especially. Pay attention in the example where by_name exists only while it is being used.
    Code:
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <vector>
    
    class Person {
    private:
        std::string name;
    public:
        Person( const char * my_name = "John Doe" ) : 
           name( my_name )
        {
        }
        virtual ~ Person( ) 
        {
        }
        std::string getName( ) const
        {
            return name;
        }
    };
    
    class Student: public Person {
    private:
        double      gpa;
        bool        present;
    public:
        Student( const char * my_name = "John Doe", double gpa_in = 3.0, bool attended = true ) : 
        Person( my_name ), gpa( gpa_in ), present( attended )
        {
        }
    
        bool isPresent( ) const
        {
            return present;
        }
    };
    
    
    template< class Handle > struct by_name {
        bool operator( ) ( const Handle &lst, const Handle &rst ) const
        {
            return lst.Person::getName() < rst.Person::getName();
        }
    };
    
    
    int main( )
    {
        std::vector< Student > classroom;
        classroom.push_back( Student( "Mary Jane", 3.75 ) );
        classroom.push_back( Student( "Oliver Warbucks", 2.9, false ) );
        classroom.push_back( Student( "Troy Percival", 4.0, false ) );
        classroom.push_back( Student( "Donna Mosley", 3.15, true ) );
        classroom.push_back( Student( "Gary Gadget" ) );
    
        std::cout << "Roll call!!\n\n";
    
        std::sort( classroom.begin(), classroom.end(), by_name< Student >() );
        for( std::vector< Student >::iterator iter = classroom.begin();
            iter != classroom.end(); iter++ )
            std::cout << iter->getName() << " is " << ( iter->isPresent()? "here\n":"not here\n" );
    
        std::cout << '\n';
        std::cout << "John Doe " <<
            ( std::binary_search( classroom.begin(), classroom.end(), "John Doe", by_name< Student >() )? "is":"is not" )<<
            " in the classroom\n";
    }
    My output:
    Roll call!!

    Donna Mosley is here
    Gary Gadget is here
    Mary Jane is here
    Oliver Warbucks is not here
    Troy Percival is not here

    John Doe is not in the classroom
    Last edited by whiteflags; 11-17-2007 at 03:24 AM. Reason: Now complete and const correct!

  5. #5
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Another adavantage of functor objects is that the compiler can inline the functor call much easier than a raw function pointer.

    gg

Popular pages Recent additions subscribe to a feed