有没有办法分解模板指向函数的指针?

rev*_*rev 6 c++ templates function-pointers

目前我有一个这样的模板:

template<typename func, typename ret, typename... args> class Entry{
public:
    PVOID Address;
    ret operator()(args...){
        return ((func) this->Address)(args...);
    }
};
Run Code Online (Sandbox Code Playgroud)

而我正在使用它:

Entry<int(*)(int), int, int> func;
//    ^func        ^ret ^args
func.Address = (PVOID) 0xDEADC0DE;
func(123); // calls 0xDEADC0DE with '123' as argument
Run Code Online (Sandbox Code Playgroud)

但是,我想知道是否有可能只有这个:

Entry<int(*)(int)> func;
//    ^only specifying the function's prototype once instead of breaking it down
func(123);
Run Code Online (Sandbox Code Playgroud)

如果我有这样的话,我将无法重载,operator()因为我无法将函数指针类型拆分为参数和返回类型(以便我可以写return_type operator()(args...)).

有没有办法实现这个目标?

我正在使用VS2013 2013年11月的CTP

Win*_*ute 5

你可以用这样的专业化来做到这一点:

// Entry has one template argument
template<typename func> class Entry;

// and if it's a function type, this specialization is used as best fit.
template<typename ret, typename... args> class Entry<ret(args...)>{
public:
  PVOID Address;
  ret operator()(args... a){
    return ((ret(*)(args...)) this->Address)(a...);
  }
};

int main() {
  Entry<int(int)> foo;
  foo.Address = (PVOID) 0xdeadc0de;
  func(123);
}
Run Code Online (Sandbox Code Playgroud)

要像在你的例子中一样使用函数指针类型(尽管我更喜欢函数类型语法),写一下

//                                            here ------v
template<typename ret, typename... args> class Entry<ret(*)(args...)>{
Run Code Online (Sandbox Code Playgroud)

附录:当我外出吃饭时还有一件事发生在我身上:有一个(轻微的)问题operator()可能会或可能不会引起你的关注:你不会遇到通过值或左值传递的参数的转发问题引用因为它们只是在传入时传递(因为参数列表对于函数指针和它完全相同operator()),但是如果你打算使用rvalue-reference参数,那么这对它们不起作用.为此原因,

Entry<int(int&&)> foo;
foo(123);
Run Code Online (Sandbox Code Playgroud)

不编译.如果计划将此函数与带有右值引用的函数一起使用,operator()可以像这样修复:

ret operator()(args... a){
  //                   explicit forwarding ----v
  return ((ret(*)(args...)) this->Address)(std::forward<args>(a)...);
}
Run Code Online (Sandbox Code Playgroud)