Please help me write a functor template

D

daniel.w.gelder

Hello, I have been trying to write a functor template for a week now
and I'm just having tons of trouble because I don't understand an issue
that I guess is pretty basic to this task.

functor<bool (long, long)> myFunctor;
myFunctor = AFunctionOfThatPrototype;

To get that much is elementary because the template can just store a
(bool)(long,long) as a member variable in functor<T>. Here is the
problem:

bool whether = myFunctor(1,2);

How can I possibly ever utilize the individual result and parameter
type from the prototype in functor::eek:perator()? I have been poring over
several template libraries and I just can't see how they accomplish it
with partial specialization. After all, I can't debug the compiler
itself or look at preprocessor source to figure out what's happening.

I understand that I could always settle for this syntax fairly easily:

functor<bool, long, long> myFunctor;
bool whether = myFunctor(4,5);

And then use a typedef inside the template to make the prototype. But
the libraries I've seen don't have to settle for that. How is this
trick done??? If it matters, I'm using XCode. Thank you very much in
advance,

Yours,
Dan
 
V

Victor Bazarov

Hello, I have been trying to write a functor template for a week now
and I'm just having tons of trouble because I don't understand an issue
that I guess is pretty basic to this task.

functor<bool (long, long)> myFunctor;

Perhaps you wanted

functor said:
myFunctor = AFunctionOfThatPrototype;

To get that much is elementary because the template can just store a
(bool)(long,long) as a member variable in functor<T>. Here is the
problem:

bool whether = myFunctor(1,2);

How can I possibly ever utilize the individual result and parameter
type from the prototype in functor::eek:perator()?

I am not sure what you mean here, but you need to implement that operator
to "utilize the individual result".
I have been poring over
several template libraries and I just can't see how they accomplish it
with partial specialization. After all, I can't debug the compiler
itself or look at preprocessor source to figure out what's happening.

I understand that I could always settle for this syntax fairly easily:

functor<bool, long, long> myFunctor;
bool whether = myFunctor(4,5);

And then use a typedef inside the template to make the prototype. But
the libraries I've seen don't have to settle for that. How is this
trick done??? If it matters, I'm using XCode. Thank you very much in
advance,

Well, if I understood your requirements and your comprehension of the
problem, you should be able to fill in the blanks here:

template<class F> class functor
{
F f; // that's something to what your functor
// delegates the functionlity
public:
functor& operator = (F ff) { ??? }
bool operator ()(long l1, long l2) { ??? }
};

The blanks I was talking about are indicated by ???

Of course, a parameterized constructor might be useful as well, so you
could write

functor<bool (*)(long,long)> myFunctor = AFunctionOfThatPrototype;

instead of using two statements.

Good luck!

V
 
R

Rob Williscroft

wrote in in
comp.lang.c++:
I understand that I could always settle for this syntax fairly easily:

functor<bool, long, long> myFunctor;
bool whether = myFunctor(4,5);

#include <iostream>
#include <ostream>

int function( int a, int b )
{
std::cout << "function( " << a << ", " << b << " );\n";
return 0;
}

/* declaration, no defenition
*/
template < typename F > struct functor;

/* Example, just the one specialization
*/
template < typename R, typename A1, typename A2 >
struct functor< R( A1, A2 ) >
{
functor( R arg(A1, A2) ) : f( arg ) {}
R operator () ( A1 a1, A2 a2 )
{
return f( a1, a2 );
}

private:
R (*f) ( A1, A2 );
};



int main()
{
functor< int( int, int ) > f( function );
return f( 1, 2 );
}


You will need to provide a specialization for each arity (number
of arguments) you want to support, also you might want to use
somthing to add `const &` to the paramiter types of the operator.

Untested code:

....

R operator () (
typename add_cref< A1 >::type a1,
typename add_cref< A2 >::type a2
)
{
return f( a1, a2 )
}

....

template < typename T > struct add_cref
{
typedef T const &type;
};
template < typename T > struct add_cref< T const & >
{
typedef T const &type;
};
template < typename T > struct add_cref< T & >
{
typedef T &type;
};

HTH.

Rob.
 
D

daniel.w.gelder

Hmm. Couple of interesting things...

1. There seems to be no problem using const& like anything else, so I
haven't implemented add_cref.

2. When the prototype has no parameters I have to phrase it different
ways in different compilers.

template < typename R > class functor< R() > // this is fine in xcode,
breaks metrowerks
template < typename R > class functor< R(*)() > // vice versa

Weird...I'll keep exploring.

Dan
 
R

Rob Williscroft

wrote in in
comp.lang.c++:
Hmm. Couple of interesting things...

1. There seems to be no problem using const& like anything else, so I
haven't implemented add_cref.

Quite right too, never solve problems you don't have :).
2. When the prototype has no parameters I have to phrase it different
ways in different compilers.

template < typename R > class functor< R() > // this is fine in xcode,
breaks metrowerks

It should work, try: < R( void ) >.

Also its a good idea to give compiler version and platform as well
as vendor, somebody with the same or a similar configuration might
be able to provide a work around. Unfortunatly I don't have a
Metroworks compiler so I can't look for one myself.
template < typename R > class functor< R(*)() > // vice versa

Weird...I'll keep exploring.

Not really R(*)() is function-pointer, R() is function type
and this is one of the situations where a function type doesn't
decay to a function-pointer type, IOW it really shouldn't work.

Rob.
 
D

daniel.w.gelder

Well, since it isn't supposed to work I found a different way: if the
function returns a Homer, you just declare functor<Homer>, which is
reasonable to me as long as I can still declare functor<Homer (J,
Simpson)>. Following source is how I do it for 0 params. The emptiness
param is so it doesn't confuse the partial specialization with the
original definition.

(BTW Rob, putting void in the defintion seems to make no difference on
XCode 1.5 or MWCW 8. What compiler are you using?)

struct emptiness {};
template < typename F , typename E=emptiness > class functor;
// zero params alt syntax
template < typename R > class functor< R, emptiness>
{
typedef R(*pt)();
pt _pt;

public:
functor( ) : _pt( 0 ) {}
functor( pt arg ) : _pt( arg ) {}
R operator () ( ) const { return _pt( ); }
functor& operator = (pt arg) { _pt = arg; return *this; }
};
 
R

Rob Williscroft

wrote in in
comp.lang.c++:
Well, since it isn't supposed to work I found a different way: if the
function returns a Homer, you just declare functor<Homer>, which is
reasonable to me as long as I can still declare functor<Homer (J,
Simpson)>. Following source is how I do it for 0 params. The emptiness
param is so it doesn't confuse the partial specialization with the
original definition.

(BTW Rob, putting void in the defintion seems to make no difference on
XCode 1.5 or MWCW 8. What compiler are you using?)

struct emptiness {};
template < typename F , typename E=emptiness > class functor;
// zero params alt syntax
template < typename R > class functor< R, emptiness>
{
typedef R(*pt)();
pt _pt;

public:
functor( ) : _pt( 0 ) {}
functor( pt arg ) : _pt( arg ) {}
R operator () ( ) const { return _pt( ); }
functor& operator = (pt arg) { _pt = arg; return *this; }
};

Looks good, but I'm not sure I see the need for the emptyness
paramiter why not just have the unspecialized version handle
0 paramiter case:

template < typename R > class functor
{
typedef R(*pt)();
pt _pt;

public:
functor( ) : _pt( 0 ) {}
functor( pt arg ) : _pt( arg ) {}
R operator () ( ) const { return _pt( ); }
functor& operator = (pt arg) { _pt = arg; return *this; }
};

Rob.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,008
Latest member
HaroldDark

Latest Threads

Top