如何提取函数指针的参数作为类型参数包?
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);
}
哪里
subclass
自动升级为 BaseClass
- 参数自动从
int
转换为float
- 使用错误的参数类型调用/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...
,用于传递给 invoke
的 args...
.
您可以按如下方式统一此包
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);
}
我愿意支持这样的调用
class BaseClass {
public:
virtual void print2(float arg1, float arg2) = 0;
};
int main() {
invoke(subclass, &BaseClass::print2, 1, 2);
}
哪里
subclass
自动升级为BaseClass
- 参数自动从
int
转换为float
- 使用错误的参数类型调用/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...
,用于传递给 invoke
的 args...
.
您可以按如下方式统一此包
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);
}