开发者

local variable as non-type template argument

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);
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜