I want to do something like the following:
Example(&Class::MemberFunction, this));
//...
template<class T_CLASS>
inline static void Example(void (T_CLASS::*MemberFunctionPointer)(), T_CLASS* InstancePointer)
{
SomeClass<T_CLASS>::Bind<MemberFunctionPointer>(InstancePointer);
}
But I g开发者_开发知识库et the error: *template parameter 'T_MEMBER_FUNCTION' : 'MemberFunctionPointer' : a local variable cannot be used as a non-type argument*
Any solutions for this problem? I want to provide an easier way to call "Bind"
Thanks, Mirco
//edit:
I want MemberFunctionPointer to be a non-type template parameter because in "Bind" I again need it as a template argument. As you wrote in your answers, in my case MemberFunctionPointer is a variable and its value is unknown at compile time. But MemberFunctionPointer always points to the same function. Is there a way to for example make it constant so that the compiler knows it at compile time?
There are two kinds of things template parameters can be: types and compile-time constant expressions. The contents of a function parameter is not a compile-time determinable value. And therefore, the compiler cannot instantiate a template based on it.
Remember: a template is a type. And types must be determinable at compile time.
You probably should pass the member pointer as an argument to the Bind
function.
I am not quite sure what you are trying to achieve?
If a MemberFunctionPointer
is a variable, that the value of is unknown at compile time and, for example, may depend on some user behaviour - then it cannot be used as a template argument.
If, on the other hand, MemberFunctionPointer
can be actually deduced at compile-time, you should pass it as a template argument, instead of a function parameter. Consider the following example:
(use Bind
and call
in the first case; in the second case, use StaticBind
and callStatic
)
#include <stdio.h>
class X {
public:
int x;
void foo() {printf("foo\n");}
void bar() {printf("bar\n");}
};
template <typename T>
class SomeClass {
public:
static void Bind(void (T::*MemberFunctionPointer)(), T *obj) {
(obj->*MemberFunctionPointer)();
}
template <void (T::*MemberFunctionPointer)()>
static void StaticBind(T *obj) {
(obj->*MemberFunctionPointer)();
}
};
template <class C>
static inline void call(void (C::*MemberFunctionPointer)(), C *obj) {
SomeClass<C>::Bind(MemberFunctionPointer,obj);
}
template <class C, void (C::*MemberFunctionPointer)()>
static inline void callStatic(C *obj) {
SomeClass<C>::template StaticBind<MemberFunctionPointer>(obj);
}
int main() {
X obj;
call<X>(&X::foo,&obj);
callStatic<X,&X::bar>(&obj);
return 0;
}
Template parameters have to be known at compile-time. The contents of a pointer variable that is a function's parameter depends on how this function is invoked. This is not known at compile-time!
If you know this pointer at compile-time already, you can turn the function pointer runtime parameter into a template parameter:
template<class T_CLASS, void(T_CLASS::*MemFunPtr)()>
void Example(T_CLASS* InstancePointer) {...}
Here, MemFunPtr is a template parameter that is known at compile-time and can thus be resused as a template parameter for another function or class template...
MemberFunctionPointer
is a variable not a type (or compile-time constant), hence cannot be used, what you need is the real signature of that function, something like this may be better..
template<typename T_FUNC_PTR, class T_CLASS>
inline static void Example(T_FUNC_PTR fPtr, T_CLASS* InstancePointer)
{
SomeClass<T_CLASS>::Bind<T_FUNC_PTR>(fPtr, InstancePointer);
}
i.e. let the compiler deduce the type of the function pointer (NOTE: you will have to propagate the pointer to the function too), to call
Example(&foo::bar, foo_inst);
This is untested and off the top of my head, so the syntax could be slightly off...
EDIT: here is a simpler example to demonstrate the concept:
#include <iostream>
struct foo
{
void bar() { std::cout << "foo::bar()" << std::endl; }
};
template<typename T_FUNC_PTR, typename T_CLASS>
void exec(T_FUNC_PTR ptr, T_CLASS& inst)
{
(inst.*ptr)();
}
int main(void)
{
foo inst;
exec(&foo::bar, inst);
}
精彩评论