[英]How to cast “void (MyClass::*)(int)” to “void (*)(int)”?
我正在尋找如何將 class 成員轉換為 C 樣式回調。
最近我找到了特殊綁定黑客的答案,允許將 class 成員綁定到 C 樣式回調:
https://stackoverflow.com/a/39524069/5405443
I have this working code to bind function MyClass::f to C function f : But i want to avoid explicit passing cb_type as template parameter to c_bind function. 在提供的示例中, CB具有void (*)(int)類型,而Func模板參數具有void (MyClass::*)(int)類型。
template<typename CB, typename Func, typename... Params>
CB* c_bind(std::_Bind<Func(Params...)> function) {
return Callback<typename ActualType<CB>::type, __COUNTER__, Func>::getCallback(function);
}
typedef void (cb_type)(int);
class MyClass {
public:
void f(int x) {
std::cout << "Hello from MyClass::f(int), value: " << x << std::endl;
}
};
int main() {
MyClass mc;
auto f = c_bind<cb_type>(std::bind(&MyClass::f, mc, std::placeholders::_1));
// ^ how to avoid explicit callback type declaration here?
f(10);
return 0;
}
我還發現了這段代碼( https://gist.github.com/vikchopde/73b62314379f733e8938f11b246df49c )用於“展開”某種功能。
bool ok = fu::is_unwrappable<decltype(&MyClass::f)>::value; // always false
// fu::unwrap_function<decltype(&MyClass::f)>::type::function_ptr blah; // won't compile
但它不會以我不知道的原因起作用。
我的問題是有什么解決方法可以從具有類成員指針(如void (MyClass::*)(int)和構造類 C 類型void (*)(int) )的類型中提取返回類型和參數列表?
感謝您的任何幫助!
好吧,在 C++17 中,您可以使用template<auto>
將任意非類型參數傳遞給 class 。 因此,我們可以將MyClass::f
存儲為模板參數並使用decltype
解析其類型。 將此類型傳遞給另一個模板化 class 后,我們可以使用模板特化提取所需的類型。
下面的代碼展示了如何構造一個 C 風格的 function wrapper<>::func_type
。
由於您似乎將 object 綁定到其成員 function,因此我另外編寫了演示代碼通過調用wrapper<>::bind
來執行此操作。 希望能幫助到你。
class MyClass {
public:
void f(int x) {
std::cout << "Hello from MyClass::f(int), value: " << x << std::endl;
}
};
void f(int x) {
std::cout << "Hello from f(int), value: " << x << std::endl;
}
template<auto F>
struct wrapper
{
template<typename> struct inner;
template<class Cls, typename Ret, typename... Args>
struct inner<Ret(Cls::*)(Args...)>
{
using func_type = Ret(Args...);
static auto bind(Cls *obj)
{
return [=](Args ...args){
return (obj->*F)(std::forward<Args>(args)...);
};
}
};
using func_type = typename inner<decltype(F)>::func_type;
static const constexpr auto bind = inner<decltype(F)>::bind;
};
int main() {
MyClass mc;
auto h = wrapper<&MyClass::f>::bind(&mc);
h(10);
using func_t = typename wrapper<&MyClass::f>::func_type;
std::function<func_t> g = f;
g(1);
return 0;
}
首先,我要感謝@Dappur 的好例子。 使用您的指南,我稍后將使用 std::_Bind 使用重寫我丑陋的綁定接口。 我還要感謝@Sam Varshavchik 提到那套 C++ 書籍。 我將開始閱讀它以成為像您一樣的 C++ 大師,以了解“為什么我不能像這樣施放它”。 但不幸的是,憑借我糟糕的 c++ 經驗,我現在仍然可以做到。 這是工作代碼:
template<class T, unsigned int n, class CallerType>
struct CallbackWrapper;
template<class Ret, class... Params, unsigned int n, class CallerType>
struct CallbackWrapper<Ret(Params...), n, CallerType> {
static auto get(std::function<Ret(Params...)>&& fn) -> Ret(*)(Params...) {
func = fn;
return static_cast<Ret(*)(Params...)>(CallbackWrapper<Ret(Params...), n, CallerType>::callback);
}
private:
static std::function<Ret(Params...)> func;
static Ret callback(Params... args) {
return func(args...);
}
};
template<class Ret, class... Params, unsigned int n, class CallerType>
std::function<Ret(Params...)> CallbackWrapper<Ret(Params...), n, CallerType>::func;
template<typename T>
struct lambda_to_stdf {
using type = void;
};
template<typename Ret, typename Class, typename... Args>
struct lambda_to_stdf<Ret(Class::*)(Args...) const> {
using type = std::function<Ret(Args...)>;
};
template<class Ret, class Cls, class... Args1, class... Args2>
auto c_bind(std::_Bind<Ret(Cls::*(Cls, Args1...))(Args2...)> function) -> Ret(*)(Args2...) {
return CallbackWrapper<Ret(Args2...), __COUNTER__, Ret(Cls::*(Cls, Args1...))(Args2...)>::get(std::move(function));
}
template<class Ret, class... Args>
auto c_bind(std::function<Ret(Args...)> function) -> Ret(*)(Args...) {
return CallbackWrapper<Ret(Args...), __COUNTER__, std::function<Ret(Args...)>>::get(std::move(function));
}
template<class F>
auto c_bind(F function) -> decltype(c_bind((typename lambda_to_stdf<decltype(&F::operator())>::type)(function))) {
return c_bind((typename lambda_to_stdf<decltype(&F::operator())>::type)(function));
}
用法:
class MyClass {
public:
void f(int x) {
std::cout << "Hello from MyClass::f(int), value: " << x << std::endl;
}
};
int main() {
MyClass mc;
auto f = c_bind(std::bind(&MyClass::f, mc, std::placeholders::_1));
f(10);
std::function<void(int)> stdf = [](int v) {
std::cout << "hello from std::function, value: " << v << std::endl;
};
auto f2 = c_bind(stdf);
f2(100);
auto f3 = c_bind([](int v) -> int {
std::cout << "hello from lambda, value: " << v << std::endl;
return 5.0f;
});
f3(1000);
return 0;
}
希望它對某人有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.