Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

passing pointer to member function as template argument

0 views
Skip to first unread message

sto...@profuse.ro

unread,
May 21, 1999, 3:00:00 AM5/21/99
to
Hello All,

I've been trying to pass a pointer to member function as a template
parameter to a templated class. No matter what, I can't do it.

Having

struct Example
{
int m_Int;

int getInt() const { return m_Int; }
};

I would like to do something like this:


// pass Example::getInt as a template parameter
TryTemplate< Example, int, Example::getInt> instance;

Frankly, I'm not even sure if the standard allows this.

Does the standard allow this?
If yes, how can I do it? (or I did it right, only that VC does not
allow it :-( )


I've made an example, which (of course), never compiles successfully.

// Compiled with VC 6.0

template<
class Class,
class Type,
Type ( Class::* GetFunction)() const>
// I tried first
//'typename Type ( typename Class::* GetFunction)()
const'
// and VC issued a very strange error
// however, which is Standard conforming?
class Try
{
};

struct Example
{
int m_Int;

int getInt() const { return m_Int; }
};

void func( int ( Example::* f) () const)
{
Example e;
int n = ( e.*f)();
}
void main()
{

typedef int ( Example::* GetIntFunction)() const;

// works fine
func( Example::getInt);

// works fine
func( ( GetIntFunction) Example::getInt);

// generates error (1):
//
// error C2440: 'specialization' : cannot convert from ''
// to 'int (__thiscall Example::*)(void)'
// None of the functions with this name in scope match the
target type
//
// generates error (2):
//
// error C2975: 'Try' : invalid template argument
// for 'GetFunction', constant expression expected
//
// generates error (3):
//
// error C2079: 'first_instance' uses undefined class
// 'Try<struct Example,int,0>'
Try< Example, int, Example::getInt> first_instance;

// generates error:
//
// error C2440: 'specialization' : cannot convert from
// 'int (__thiscall Example::*)(void) const' to
// 'int (__thiscall Example::*)(void)'
//
// ( + also generates errors 2 & 3 from above
Try< Example, int, ( GetIntFunction)Example::getInt>
second_instance;
}


Thanks to those who answer.

John


--== Sent via Deja.com http://www.deja.com/ ==--
---Share what you know. Learn what you don't.---

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]

Siemel Naran

unread,
May 22, 1999, 3:00:00 AM5/22/99
to
On 21 May 1999 22:28:35 -0400, sto...@profuse.ro <sto...@profuse.ro> wrote:

>template<
> class Class,
> class Type,
> Type ( Class::* GetFunction)() const>
> // I tried first
> //'typename Type ( typename Class::* GetFunction)() const'
> // and VC issued a very strange error
> // however, which is Standard conforming?
> class Try
>{
>};

Fine.
The 'typename' in "typename Type(...) const" is redundant and an error,
but I think it should be allowed, just because.


>struct Example
>{
> int m_Int;
>
> int getInt() const { return m_Int; }
>};
>
>void func( int ( Example::* f) () const)
>{
> Example e;
> int n = ( e.*f)();
>}

>void main()

Should be int main() because the return type of the program may be used
by the operating system. For example, we can write a shell script or
batch file that calls your program as one of its steps.


> // works fine
> func( Example::getInt);

Almost fine. The standard requires the use of '&' in taking the
address of a member function. But most compilers don't complain if
you leave it out. Use
func( &Example::getInt);

> // works fine
> func( ( GetIntFunction) Example::getInt);

Almost fine, as above.
But this is awful. Forcing a cast on a function type is dangerous
business as you may end up calling a function with the wrong type of
arguments, in which case the program will crash or do something
worse. Besides, the cast is unnecessary.
In any case, my advice is to avoid C style casts on pointer and
reference types altogether.

> // generates error (1):


> Try< Example, int, Example::getInt> first_instance;

Remember the '&', and your program should compile.
Try< Example, int, &Example::getInt> first_instance;
My compilers require the '&' for template arguments but not function
arguments.


> Try< Example, int, ( GetIntFunction)Example::getInt>
second_instance;

Awful.

Another design is to leave out pointer to functions.
template<class Class, class Result>
class Try {
private:
Result (Class::*const calculate)() const;
public:
explicit Try(Class::*const calculate) : calculate(calculate) { }
...
};

--
----------------------------------
Siemel B. Naran (sbn...@uiuc.edu)
----------------------------------

Carl Barron

unread,
May 22, 1999, 3:00:00 AM5/22/99
to
You can pass the pointer to the member function as a parameter of a
constructor in the template as in:
// start of code
#include <functional>
using std::mem_fun_t;
using std::mem_fun;

/*


template<
class Class,
class Type,
Type ( Class::* GetFunction)() const>

class Try
{
};
*/

template <class Class,class Type >
class Try
{
mem_fun_t<Type,Class> func_;
public:
explicit Try(mem_fun_t<Type,Class> f):func_(f){}
Type operator () (Class &x) {return func_();}
};

struct Example
{
int m_Int;

int getInt() const { return m_Int; }
};

int main()
{

Try< Example, int> first_instance(mem_fun(&Example::getInt));
}

// end of code

<sto...@profuse.ro> wrote:

> Hello All,
>
> I've been trying to pass a pointer to member function as a template
> parameter to a templated class. No matter what, I can't do it.
>

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

sto...@profuse.ro

unread,
May 24, 1999, 3:00:00 AM5/24/99
to
In article <slrn7kcacc....@localhost.localdomain>,

sbn...@uiuc.edu wrote:
> On 21 May 1999 22:28:35 -0400, sto...@profuse.ro <sto...@profuse.ro>
wrote:
>
> >template<
> > class Class,
> > class Type,
> > Type ( Class::* GetFunction)() const>
> > // I tried first
> > //'typename Type ( typename Class::* GetFunction)()
const'
> > // and VC issued a very strange error
> > // however, which is Standard conforming?
> > class Try
> >{
> >};
>
> Fine.
> The 'typename' in "typename Type(...) const" is redundant and an
error,
> but I think it should be allowed, just because.
>
> >struct Example
> >{
> > int m_Int;
> >
> > int getInt() const { return m_Int; }
> >};
> >
> >void func( int ( Example::* f) () const)
> >{
> > Example e;
> > int n = ( e.*f)();
> >}
>
> >void main()
>
> Should be int main() because the return type of the program may be
used
> by the operating system. For example, we can write a shell script or
> batch file that calls your program as one of its steps.
>

true.

> > // works fine
> > func( Example::getInt);
>
> Almost fine. The standard requires the use of '&' in taking the
> address of a member function. But most compilers don't complain if

Of course! I forgot...

> you leave it out. Use
> func( &Example::getInt);
>
> > // works fine
> > func( ( GetIntFunction) Example::getInt);
>
> Almost fine, as above.
> But this is awful. Forcing a cast on a function type is dangerous
> business as you may end up calling a function with the wrong type of
> arguments, in which case the program will crash or do something
> worse. Besides, the cast is unnecessary.
> In any case, my advice is to avoid C style casts on pointer and
> reference types altogether.

I agree COMPLETELY. The only reason I did that was to help the
compiler generate more accurate error messages (since I know
VC has problems with templates).
However, I didn't work too well...

> > // generates error (1):
> > Try< Example, int, Example::getInt> first_instance;
>
> Remember the '&', and your program should compile.
> Try< Example, int, &Example::getInt> first_instance;
> My compilers require the '&' for template arguments but not function
> arguments.
>

I wish that were true. However, VC still generates the errors above...

> [...]


>
> Another design is to leave out pointer to functions.
> template<class Class, class Result>
> class Try {
> private:
> Result (Class::*const calculate)() const;
> public:
> explicit Try(Class::*const calculate) : calculate(calculate)
{ }
> ...
> };
>

In my problem, it would have been a lot easier using pointers to member
functions as template parameters, but I guess I have to compromise...
So, I will probably change the design.
Thanks.

John


--== Sent via Deja.com http://www.deja.com/ ==--
---Share what you know. Learn what you don't.---

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

0 new messages