Question

I use Visual C++ 2012. I want to parameterize a template function with a pointer to another function. It all works nicely outside of a class:

int add(int a, int b) {
   return a + b;
}
typedef int (*func)(int a, int b);
template<func F> int do_it(int a, int b) {
   return F(a, b);
}
int foo(int a, int b) {
   return do_it<add>(a, b);
}

Visual C++ 2012 compiles and optimizes that perfectly.

Now, I put it inside a class and adjust it for pointer-to-member:

struct S {
   int add(int a, int b) {
      return a + b;
   }
   typedef int (S::*func)(int a, int b);
   template<func F> int do_it(int a, int b) {
      return F(a, b);     // <-- here be error!
   }
   int foo(int a, int b) {
      return do_it<&S::add>(a, b);
   }
};
S s;

int bar(int a, int b) {
   return s.foo(a, b);
}

But that gives me a compiler-error:

Microsoft (R) C/C++ Optimizing Compiler Version 17.00.51106.1 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

x2.cpp
x2.cpp(7) : error C2064: term does not evaluate to a function taking 2 arguments
        x2.cpp(10) : see reference to function template instantiation 'int S::do_it<int S::add(int,int)>(int,int)' being compiled

Any idea why and how to fix it?

Was it helpful?

Solution

The syntax for pointers to members still apply. You should write :

typedef int (S::*func)(int a, int b);
   template<func F> int do_it(int a, int b) {
      return (this->*F)(a, b);
   }

Using a pointer to member always require associating an object with it - here, it makes sense you would call your pointer on this.

OTHER TIPS

Member-function pointers must be called on an object; unlike a normal member function call, this must be specified explicitly:

(this->*F)(a,b);

Although, if the function doesn't need to access this, perhaps it should be static (or a non-member), specified by a normal function pointer.

It looks like you just need to call the member function pointer on an object:

template<func F> int do_it(int a, int b) {
      return (this->*F)(a, b);
}

Pointers to members always need to be called on an object, unlike free and static member functions, which is why you need the above syntax.

You need to provide the object when calling a pointer-to-meber function:

(this->*F)(a, b);

One point further: write your "do_it" more generally as

template<class F> int do_it(F f, int a, int b) {
   return f(a, b);        }

Now, you can pass it any function of two integers:

int mul(int a, int b) { return a*b ; }
S s;
s.do_it(mul,2,3);

When you intend to use it inside your class with a member function, just bind it with this. Using boost::bind,

   int foo(int a, int b) {
       return do_it( boost::bind(&S::add,this,_1,_2),a,b)  ;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top