我正在寻找如何将类成员转换为C风格的回调。
最近,我发现带有特殊绑定hack的答案允许将类成员绑定到C风格的回调:
https://stackoverflow.com/a/39524069/5405443
我有此工作代码将函数MyClass :: f绑定到C函数f:但我想避免将cb_type作为模板参数显式传递给c_bind函数。在提供的示例中,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
但由于我的未知,它不会起作用。
我的问题是是否有任何变通办法来从具有类成员指针的类型中提取返回类型和args列表,如void(MyClass :: *)(int)和构造C类的void(*)(int)?
感谢您的任何帮助!
首先,我要感谢@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;
}
希望对某人有帮助。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句