如何在推导的上下文中将 std::bind (或 lambda) 转换为 std::function
How to convert std::bind (or lambda) to std::function in deduced context?
我正在尝试将指向成员函数的指针(使用 std::bind
或 lambdas)转换为std::function
。我的尝试(按照SO上的这个答案的答案)看起来像这样:
#include <functional>
template<typename T>
struct AsFunction :
AsFunction<decltype(&T::operator())>
{};
template<class ReturnType, class... Args>
struct AsFunction<ReturnType(Args...)> {
using type = std::function<ReturnType(Args...)>;
};
template<class ReturnType, class... Args>
struct AsFunction<ReturnType(*)(Args...)> {
using type = std::function<ReturnType(Args...)>;
};
template<class Class, class ReturnType, class... Args>
struct AsFunction<ReturnType(Class::*)(Args...) const> {
using type = std::function<ReturnType(Args...)>;
};
template<class F>
auto toFunction( F f ) -> typename AsFunction<F>::type {
return {f};
}
struct MyStruct {
int x,y;
void f(int){};
};
int main(){
MyStruct m;
{
// this works
auto f = std::bind(&MyStruct::f, &m, std::placeholders::_1);
f(2);
}
{
// this doesn't
auto f = toFunction(std::bind(&MyStruct::f, &m, std::placeholders::_1));
f(2);
}
{
// .. neither does this
auto f = toFunction([m](int x) mutable { m.f(x); });
f(2);
}
}
但我从编译器收到以下错误消息:
// first not working
main.cpp:24:6: note: substitution of deduced template arguments resulted in errors seen above
main.cpp: In instantiation of ‘struct AsFunction<std::_Bind<std::_Mem_fn<void (MyStruct::*)(int)>(MyStruct*, std::_Placeholder<1>)> >’:
main.cpp:24:6: required by substitution of ‘template<class F> typename AsFunction<F>::type toFunction(F) [with F = std::_Bind<std::_Mem_fn<void (MyStruct::*)(int)>(MyStruct*, std::_Placeholder<1>)>]’
main.cpp:44:75: required from here
main.cpp:4:8: error: decltype cannot resolve address of overloaded function
struct AsFunction :
^~~~~~~~~~
main.cpp: In function ‘int main()’:
main.cpp:44:75: error: no matching function for call to ‘toFunction(std::_Bind_helper<false, void (MyStruct::*)(int), MyStruct*, const std::_Placeholder<1>&>::type)’
auto f = toFunction(std::bind(&MyStruct::f, &m, std::placeholders::_1));
^
main.cpp:24:6: note: candidate: template<class F> typename AsFunction<F>::type toFunction(F)
auto toFunction( F f ) -> typename AsFunction<F>::type {
^~~~~~~~~~
main.cpp:24:6: note: substitution of deduced template arguments resulted in errors seen above
// second non working braces with lambda
main.cpp: In instantiation of ‘struct AsFunction<void (main()::<lambda(int)>::*)(int)>’:
main.cpp:4:8: required from ‘struct AsFunction<main()::<lambda(int)> >’
main.cpp:24:6: required by substitution of ‘template<class F> typename AsFunction<F>::type toFunction(F) [with F = main()::<lambda(int)>]’
main.cpp:50:55: required from here
main.cpp:5:23: error: ‘operator()’ is not a member of ‘void (main()::<lambda(int)>::*)(int)’
AsFunction<decltype(&T::operator())>
^~
main.cpp:50:55: error: no matching function for call to ‘toFunction(main()::<lambda(int)>)’
auto f = toFunction([m](int x) mutable { m.f(x); });
^
main.cpp:24:6: note: candidate: template<class F> typename AsFunction<F>::type toFunction(F)
auto toFunction( F f ) -> typename AsFunction<F>::type {
^~~~~~~~~~
main.cpp:24:6: note: substitution of deduced template arguments resulted in errors seen above
很难从 lambda 或 std::bind
返回类型推断出参数,因此您可能希望延迟toFunction
内部的绑定,例如:
template<typename C, typename Ret, typename... Args, typename... BArgs>
auto toFunction(Ret (C::*f)(Args...), BArgs&&... bargs) {
return std::function<Ret(Args...)>(std::bind(f, std::forward<BArgs>(bargs)...));
}
这样,您可以使用以下方法检索std::function
:
auto f = toFunction(&MyStruct::f, &m, std::placeholders::_1);
f(2);
我认为你有点矫枉过正了。如果你真的想要一个显式的std::function
类型给你的f
,你可以用一些技巧直接指定它:
int main(){
MyStruct m;
{
std::function<decltype(std::declval<MyStruct>().f(int()))(int)> f(std::bind(&MyStruct::f, &m, std::placeholders::_1));
f(2);
}
}
话虽如此,到目前为止最简单的事情是简单地使用auto f
而不指定类型。我假设你已经想到了这一点,在你的情况下它不会做,但我这么说是为了以防万一。
相关文章:
- 可组合的lambda/std::函数与std::可选
- 将带有unique_ptr的可变 lambda 传递给 const&std::function
- 捕获lambda中的std::数组
- 如何调用存储在指向"std::函数"的指针中的 lambda?
- 如果模板没有可变参数,则 Lambda 被推导出为 std::function
- 为什么我不能在 constexpr lambda 函数中使用 std::tuple
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- 将 lambda 表达式传递给 std::function in C++
- 在 lambda 表达式中使用 std::atomic
- 修改在 std::future 的 lambda 中引用捕获的值
- 在 lambda 中锁定 std::shared_ptr 的复制操作
- std::move a const std::vector in a lambda capture
- 从 std::function in C++ 访问模板化 lambda
- 如果 lambda 没有指定的类型,std::function 如何接受 lambda?
- 如何制作可以接受任何类型的参数的 std::函数和 lambda
- 是否可以将具有不同签名的 lambda 存储在 std::vector 中并在函数中执行它们(使用各自的参数)?
- 如何使用lambda作为std::unique_ptr的删除器?
- 创建一个带有 lambda 的 std::函数,而不知道函数的参数
- 针对 std::function 的 lambda 表达式和模板推导:为什么会这样?
- std::function<std::optional<T>()> 如何与返回 T 的 lambda 兼容?