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.
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.
Re: Adapter functor Creation
I hope JVene can provide an example that explain all adaptor function from STL and boost.
Thanks.
Re: Adapter functor Creation
Peter_APIIT there is no functors in your code. Functor is a class with an overloaded operator().
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.
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.