局部变量作为非类型模板参数

时间:2011-06-29 09:36:52

标签: c++ templates local non-type

我想做以下事情:

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

但我收到错误:*模板参数'T_MEMBER_FUNCTION':'MemberFunctionPointer':局部变量不能用作非类型参数*

针对此问题的任何解决方案?我想提供一种更简单的方式来调用“Bind”

谢谢,Mirco

//编辑:

我希望MemberFunctionPointer成为非类型模板参数,因为在“Bind”中我再次需要它作为模板参数。 正如您在答案中所写,在我的情况下,MemberFunctionPointer是一个变量,它的值在编译时是未知的。但是MemberFunctionPointer总是指向同一个函数。有没有办法让它保持不变,以便编译器在编译时知道它?

4 个答案:

答案 0 :(得分:4)

模板参数有两种类型:类型和编译时常量表达式。函数参数的内容不是编译时可确定的值。因此,编译器无法基于它实例化模板。

请记住:模板是类型。并且类型必须在编译时可以确定。

您可能应该将成员指针作为参数传递给Bind函数。

答案 1 :(得分:1)

我不太确定你想要达到的目标?

如果MemberFunctionPointer是变量,那么编译时的值是未知的,例如,可能取决于某些用户行为 - 那么它就不能用作模板参数。

另一方面,如果MemberFunctionPointer可以在编译时实际推断出,则应将其作为模板参数而不是函数参数传递。请考虑以下示例:

(在第一种情况下使用Bindcall;在第二种情况下,使用StaticBindcallStatic

#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;
}

答案 2 :(得分:1)

模板参数必须在编译时知道。作为函数参数的指针变量的内容取决于如何调用此函数。这在编译时是不知道的!

如果您已经在编译时知道此指针,则可以将函数指针运行时参数转换为模板参数:

template<class T_CLASS, void(T_CLASS::*MemFunPtr)()>
void Example(T_CLASS* InstancePointer) {...}

这里,MemFunPtr是一个在编译时已知的模板参数,因此可以作为另一个函数或类模板的模板参数重新使用...

答案 3 :(得分:0)

MemberFunctionPointer是一个变量而不是类型(或编译时常量),因此无法使用,你需要的是该函数的真实签名,这样的事情可能是更好..

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

即。让编译器推导出函数指针的类型(注意:你也必须传播指向函数的指针),调用

Example(&foo::bar, foo_inst);

这是未经测试的,并且不在我的脑海中,所以语法可能稍微偏离......

编辑:这是一个更简单的例子来演示这个概念:

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