Reputation: 5399
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?
Upvotes: 2
Views: 503
Reputation: 1108
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) ;
Upvotes: 0
Reputation: 154015
You need to provide the object when calling a pointer-to-meber function:
(this->*F)(a, b);
Upvotes: 1
Reputation: 254701
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.
Upvotes: 2
Reputation: 52365
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.
Upvotes: 1
Reputation: 2062
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
.
Upvotes: 4