转发成员函数到静态方法
Forward member function to static method
上下文
基本上我需要一个成员函数 const void *const
,因为它必须传递给第三方库(这意味着我不能使用 bind
、function
、 ETC)。因为这似乎是不可能的,所以我想做下一个最好的事情,将一个成员函数映射到一个静态转发方法,然后我可以获得它的指针(将 this
作为第一个参数传递)。
问题
我有很多个函数需要注册,有不同的签名,所以我想要一个很好的解决方案,允许我转换一个成员的签名将函数转换为静态方法签名(当然将 this
作为参数传递)——然后我可以将其转换为 const void* const
。所以基本上我想做这样的事情:
所以基本上:
struct Foo
{
MyType Bar(int a);
};
template <typename Ret, typename This, Ret(This::*Func)()>
struct CallWrap0
{
static Ret &&Call(This* thisPtr)
{
return thisPtr->(*Func)();
}
};
int Main()
{
const void * const memberFunction = &(CallWrap0<MyType, Foo, Foo::Bar>()::Call);
// etc.
}
这个解决方案的问题是——尽管它有效——它不是很好,因为我必须明确地告诉编译器类型。我正在寻找一个编译器可以自动填充所有管道的解决方案。
我一直在尝试使用辅助函数来解决这个问题,但到目前为止还没有成功:
template <class Ret, class T, class... Args>
const void* const FunctionPtr(Ret (T::*function)(Args... args))
{
// not sure... function is not a template, so this would require a class instance
// which is not possible due to the ext. library constraints.
}
#include <utility>
template <typename T, T t>
struct CallWrap;
template <typename Ret, typename This, typename... Args, Ret(This::*Func)(Args...)>
struct CallWrap<Ret(This::*)(Args...), Func>
{
static Ret Call(This* thisPtr, Args... args)
{
return (thisPtr->*Func)(std::forward<Args>(args)...);
}
};
int main()
{
auto f = &CallWrap<decltype(&Foo::Bar), &Foo::Bar>::Call;
}
对于无法编译上述解决方案的 MSVC,请尝试以下代码:
template <typename T>
struct CallWrap;
template <typename Ret, typename This, typename... Args>
struct CallWrap<Ret(This::*)(Args...)>
{
template <Ret(This::*Func)(Args...)>
struct Function
{
static Ret Call(This* thisPtr, Args... args)
{
return (thisPtr->*Func)(std::forward<Args>(args)...);
}
};
};
int main()
{
auto f = &CallWrap<decltype(&Foo::Bar)>::Function<&Foo::Bar>::Call;
}
上下文
基本上我需要一个成员函数 const void *const
,因为它必须传递给第三方库(这意味着我不能使用 bind
、function
、 ETC)。因为这似乎是不可能的,所以我想做下一个最好的事情,将一个成员函数映射到一个静态转发方法,然后我可以获得它的指针(将 this
作为第一个参数传递)。
问题
我有很多个函数需要注册,有不同的签名,所以我想要一个很好的解决方案,允许我转换一个成员的签名将函数转换为静态方法签名(当然将 this
作为参数传递)——然后我可以将其转换为 const void* const
。所以基本上我想做这样的事情:
所以基本上:
struct Foo
{
MyType Bar(int a);
};
template <typename Ret, typename This, Ret(This::*Func)()>
struct CallWrap0
{
static Ret &&Call(This* thisPtr)
{
return thisPtr->(*Func)();
}
};
int Main()
{
const void * const memberFunction = &(CallWrap0<MyType, Foo, Foo::Bar>()::Call);
// etc.
}
这个解决方案的问题是——尽管它有效——它不是很好,因为我必须明确地告诉编译器类型。我正在寻找一个编译器可以自动填充所有管道的解决方案。
我一直在尝试使用辅助函数来解决这个问题,但到目前为止还没有成功:
template <class Ret, class T, class... Args>
const void* const FunctionPtr(Ret (T::*function)(Args... args))
{
// not sure... function is not a template, so this would require a class instance
// which is not possible due to the ext. library constraints.
}
#include <utility>
template <typename T, T t>
struct CallWrap;
template <typename Ret, typename This, typename... Args, Ret(This::*Func)(Args...)>
struct CallWrap<Ret(This::*)(Args...), Func>
{
static Ret Call(This* thisPtr, Args... args)
{
return (thisPtr->*Func)(std::forward<Args>(args)...);
}
};
int main()
{
auto f = &CallWrap<decltype(&Foo::Bar), &Foo::Bar>::Call;
}
对于无法编译上述解决方案的 MSVC,请尝试以下代码:
template <typename T>
struct CallWrap;
template <typename Ret, typename This, typename... Args>
struct CallWrap<Ret(This::*)(Args...)>
{
template <Ret(This::*Func)(Args...)>
struct Function
{
static Ret Call(This* thisPtr, Args... args)
{
return (thisPtr->*Func)(std::forward<Args>(args)...);
}
};
};
int main()
{
auto f = &CallWrap<decltype(&Foo::Bar)>::Function<&Foo::Bar>::Call;
}