如何提取函数指针的参数作为类型参数包?

How to extract the arguments of a function pointer as type parameter pack?

我愿意支持这样的调用

class BaseClass {
public:
  virtual void print2(float arg1, float arg2) = 0;
};

int main() {
  invoke(subclass, &BaseClass::print2, 1, 2);      
}

哪里

  1. subclass 自动升级为 BaseClass
  2. 参数自动从int转换为float
  3. 使用错误的参数类型调用/class 类型导致错误

我设法解决了带有底座的部分 class。 但是论证部分让我很头疼。 我的方法是从传递的函数指针中提取所有需要的类型信息。 然后隐式转换其他参数(如果可能)。

我目前的情况是:

template<class Func> struct FunctionPointer2 {};

template<class Class, typename Arg1, typename Arg2> struct FunctionPointer2<void (Class::*)(Arg1, Arg2)> {
  typedef Class Class;
  typedef Arg1 Argument1;
  typedef Arg2 Argument2;
};

template <typename Func>
void invoke2(typename FunctionPointer2<Func>::Class* obj, Func func, typename FunctionPointer2<Func>::Argument1 arg1, typename FunctionPointer2<Func>::Argument2 arg2) {
  (obj->*func)(arg1, arg2);
}

它可以工作,但对于每个参数计数,都需要另一个函数、函数指针结构...。

那么问题来了:跟随甚至可能吗?我怎样才能让它成为可能?

template<class Func> struct FunctionPointer {};

template<class Class, typename ... Args> struct FunctionPointer<void (Class::*)(Args ...)> {
  typedef Class Class;
  typedef Args Arguments; // pass type parameter pack here
};

template <typename Func>
void invoke(typename FunctionPointer<Func>::Class* obj, Func func, typename FunctionPointer<Func>::Arguments ... params) {
  (obj->*func)(params ...);
}

谢谢你的帮助:)

手动上传和提取参数类型都应该是 没必要。

你可以这样做:

template <typename T, typename M, typename ...P>
void invoke(T &&object, M member, P &&... params)
{
    (std::forward<T>(object).*member)(std::forward<P>(params)...);
}

不确定是否理解...但是如果您希望第一个参数向上转换...我想您正在寻找

template <typename D, typename R, typename B, typename ... As1,
          typename ... As2>
void invoke (D && d, R(B::*pnt)(As1...), As2 && ... args)
 { (dynamic_cast<B&>(std::forward<D>(d)).*pnt)
      (std::forward<As2>(args)...); }

观察到有几个可变参数模板包:As1...,用于方法所需的参数,As2...,用于传递给 invokeargs... .

您可以按如下方式统一此包

template <typename D, typename R, typename B, typename ... As>
R invoke (D && d, R(B::*pnt)(As...), As && ... args)
void { (dynamic_cast<B&>(std::forward<D>(d)).*pnt)
          (std::forward<As>(args)...); }

但是很危险,因为当没有完美匹配时,编译器可能无法推断出 As... 类型(如在您的示例中,您将两个 int 传递给一个需要两个 float).

的方法

下面是一个完整的编译示例

#include <iostream>

struct BaseClass
 { virtual void print2 (float, float) = 0; };

struct Derived : public BaseClass
 {
   void print2 (float f1, float f2)
    { std::cout << f1 << ", " << f2 << std::endl; }
 };


template <typename D, typename R, typename B, typename ... As1,
          typename ... As2>
void invoke (D && d, R(B::*pnt)(As1...), As2 && ... args)
 { (dynamic_cast<B&>(std::forward<D>(d)).*pnt)
      (std::forward<As2>(args)...); }

int main()
 {
   Derived der;

   invoke(der, &BaseClass::print2, 1, 2);      
 }