CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 7 of 7
  1. #1
    Join Date
    Apr 2007
    Location
    Mars NASA Station
    Posts
    1,436

    Thumbs up Adapter functor Creation

    I would like to create a functor with 1 argument from member function.

    Code:
    Ite = std::find_if(data.begin(), data.end(),  std::mem_fun1_ref(&HumanResource::IsAdmin)  ); 
    
    bool HumanResource::IsAdmin(const std::string& department)
    {
    	if (department == "Administration")
    	{
    		return true;
    	}
    
    	return false;
    }
    What is the correct syntax ?

    Thanks.
    Thanks for your help.

  2. #2
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: Adapter functor Creation

    Quote Originally Posted by Peter_APIIT
    What is the correct syntax ?
    For starters, it depends on what is Ite and data, as well as what exactly you are trying to do. It may also depend on whether you are allowed to say, use Boost. In the end, it may well be easier to just define a helper function, e.g., in an anonymous namespace.
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  3. #3
    Join Date
    Apr 2007
    Location
    Mars NASA Station
    Posts
    1,436

    Re: Adapter functor Creation

    OK, Ite is iterator of data container point to begin().

    Yes, i allowed to use boost but i need to use std first then learn boost.

    I try to searching a sequence of string inside container to check whether it is equal to a value.

    Thanks laserlight.
    Thanks for your help.

  4. #4
    Join Date
    Apr 2007
    Location
    Mars NASA Station
    Posts
    1,436

    Re: Adapter functor Creation

    I hope JVene can provide an example that explain all adaptor function from STL and boost.

    Thanks.
    Thanks for your help.

  5. #5
    Join Date
    Apr 2009
    Location
    Russia, Nizhny Novgorod
    Posts
    99

    Re: Adapter functor Creation

    Peter_APIIT there is no functors in your code. Functor is a class with an overloaded operator().

  6. #6
    Join Date
    Nov 2006
    Posts
    1,611

    Re: Adapter functor Creation

    Well, Peter__APIIT, I’m flattered to be called out.

    Ok, to your first inquiry, the functor.

    find_if, and a number of algorithms, require a predicate. In MSDN’s documentation of find_if, they issue an example which takes this function:

    Code:
    bool greater10 ( int value )
    {
       return value >10;
    }
    …..
    
    Which is called thus:
    
    result = find_if( L.begin( ), L.end( ), &greater10 );
    So, the predicate can be satisfied with a pointer to a function of the appropriate signature.

    In order to provide a functor that does the same thing, something like this would suffice:

    Code:
    class greater10
    {
     private:
    
     int compval;
    
     public:
    
     greater10( const int cv ) : compval( cv ) {}
     
     bool operator()(int value)
      {
       return value > compval;
      }
    
    
    };
    
    …..
    In order to supply this to find_if, you must have an instance.
    
    greater10 g( 10 );
    
    result = find_if( L.begin( ), L.end( ), g );
    The instance g, having a function operator overload which takes and int and returns a bool, now supplied by value to the find_if algorithm, now still satisfies the requirement of a predicate, but with the properties of an object.

    A generic adapter could be fashioned that does something similar. Here’s one to call a non-member function

    Code:
    bool g10( const int v )
    {
     return ( v > 10 );
    }
    
    template <typename result, typename param>
    class genadapter
    {
     private:
    
     result ( *fptr )( const param );
    
     public:
    
     explicit genadapter( result ( *f ) ( const param ) ) : fptr( f ) {}
    
     result operator()( const param i )
        {
         return (*fptr)( i );
        }
    };
    
    ……..
    
    Create an instance…
    
    genadapter<bool,int> g( &g10 );
    
    Call as before
    
    result = find_if( L.begin( ), L.end( ), g );
    Which can be further assisted with the creation of a template function which creates the appropriate instantiation of the genadapter based on context

    Code:
    // here a template function called gadapter is created
    
    template<typename result, typename param>
    genadapter<result,param> 
    gadapter( result (*f)(const param) )
    {
     return genadapter<result,param>( f );
    }
    
    // no instance is required ahead of usage, as in
    
    result = find_if( L.begin( ), L.end( ), gadapter( &g10 ) );

    Similarly, an member function may be used, which requires an instance upon which to make the call….

    Code:
    class greater10
    {
     private:
    
     int compval;
    
     public:
    
     greater10( const int cv ) : compval( cv ) {}
     
     bool comp(const int value)
    {
       return value > compval;
    }
    
    
    };
    
    
    template <typename result, typename obj, typename param>
    class genadapter
    {
     private:
    
     obj * object_for_call;
     result ( obj::*fptr )( const param );
    
     public:
    
     explicit genadapter(obj &o, result ( obj::*f ) ( const param ) ) : object_for_call( &o ), fptr( f ) {}
    
     result operator()( const param i )
        {
         return (object_for_call->*fptr)( i );
        }
    };
    
    
    //an object for which a member function is to be called
    
    greater10 g10obj(10);   
    
    
    // an instance of the adapter for that member function call
    
    genadapter<bool,greater10,int> g( g10obj, &greater10::comp );
    
    
    // the usage as before
    
    result = find_if( L.begin( ), L.end( ), g );

    Which can also be assisted with a template function creater…

    Code:
    
    template<typename result, typename obj, typename param>
    genadapter<result,obj, param> 
    gadapter( obj &o, result (obj::*f)(const param) )
    {
     return genadapter<result,obj, param>( o, f );
    }
    
    // and for usage, the object must exist
    
    greater10 g10obj(10);   
    
    
    // then, find_if is:
    
    result = find_if( L.begin( ), L.end( ), gadapter( g10obj, &greater10::comp ) );

    A few points of interest…

    In the examples shown, it is not possible to infer the types when creating genadapter (of either non-member or member function versions) from context. That is, you must specify the types for the template object creation as in:

    genadapter<bool,greater10,int> g( g10obj, &greater10::comp );

    It won’t do to try something like:

    Genadapter g( g10obj, &greater10::comp );

    The compiler won’t accept this. This is the rationale for the template function gadapter, which can infer the types with

    gadapter( g10obj, &greater10::comp )

    ..likewise, find_if is also a template function, so it can, in turn, infer the types involved.

    I’ve also re-used greater10 as an example of a member function call. This may be an unfortunate choice, because it implies that you must create an object within your function where you call find_if. Note with some care that this isn’t true. Assume for a moment that your use of find_if is in a member function, possibly of a window object responding to a command. It is possible that the member function to be called is also a member of the window object (that would be ‘this’), and if so, the adapter could be fashioned for that. Let’s say the class is MyWindow, you could reasonably expect to:

    result = find_if( L.begin(), L.end(), gadapter( *this, &MyWindow::comp ) );

    The point is, any object for which an instance is available, including this, and for which a member function has an appropriate signature could qualify through the adapter to satisfy the need for a predicate.


    A little reading on boost::function, which was accepted into tr1, reveals that it performs a similar task from a pre-built library, as do std::bind1st and std::mem_fun, and can work in conjunction for something like:

    Code:
    boost:function1<bool, int> f;
    greater10 g;
    
    f = std::bind1st( std::memfun(&Greater10::comp), &g );
    
    result = find_if( L.begin(), L.end(), f );
    Though I’ve not thoroughly checked this last example for compliance.
    Last edited by JVene; July 25th, 2009 at 01:14 PM.
    If my post was interesting or helpful, perhaps you would consider clicking the 'rate this post' to let me know (middle icon of the group in the upper right of the post).

  7. #7
    Join Date
    Apr 2007
    Location
    Mars NASA Station
    Posts
    1,436

    Re: Adapter functor Creation

    First and foremost, thanks for your explanation.

    It really helpful and i appreciate that.


    Actually, i know what is functor and your functor expanation states that how to create adapter that can wraps any callable entity as function object.

    By the way, i also learn new knowledge.

    I learn three points.
    1. Class template adapter functor require template parameter
    2. function template adapter functor doesn't required template parameter
    3. Wrapping member function require class instance.


    My actual question is about the usage of STL functor adapter(mem_fun, bind1st, bind2nd) and boost bind.

    Question:
    1. Error message state that function does not take 1 arguments ?
    2. I always cannot get the binding parameter correct.

    This article doesn't explain much and i could not understand the documentation.

    boost function is really helpful which is a generic Function pointer to any callable entity.

    Thanks JVene.

    I have rated your post.
    Thanks for your help.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured