如何使用模板将lambda转换为std ::函数 [英] How to convert a lambda to an std::function using templates

查看:156
本文介绍了如何使用模板将lambda转换为std ::函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本上,我想要做的是使用任何数量的任何类型的参数的lambda,并将其转换为std ::函数。
我试过下面这两种方法都不行。

Basically, what I want to be able to do is take a lambda with any number of any type of parameters and convert it to an std::function. I've tried the following and neither method works.

std::function([](){});//Complains that std::function is missing template parameters
template <typename T> void foo(function<T> f){}
foo([](){});//Complains that it cannot find a matching candidate

下面的代码不工作,但它不是我想要的,因为它需要明确说明模板参数不适用于通用代码。

The following code does work however, but it is not what I want because it requires explicitly stating the template parameters which does not work for generic code.

std::function<void()>([](){});

我晚上一直在使用函数和模板,我只是不能想出来,所以任何帮助将非常感激。

I've been mucking around with functions and templates all evening and I just can't figure this out, so any help would be much appreciated.

如在注释中提到的,我试图这样做的原因是因为我试图实现currying在C +使用可变参数模板。不幸的是,这在使用lambdas时可怕地失败。例如,我可以使用函数指针传递标准函数。

As mentioned in a comment, the reason I'm trying to do this is because I'm trying to implement currying in C++ using variadic templates. Unfortunately, this fails horribly when using lambdas. For example, I can pass a standard function using a function pointer.

template <typename R, typename...A>
void foo(R (*f)(A...)) {}
void bar() {}
int main() {
    foo(bar);
}

然而,我不知道如何将lambda传递给可变函数。为什么我有兴趣将一个通用的lambda转换为std ::函数是因为我可以做以下,但最终要求我明确地声明模板参数std :: function这是我想避免的。

However, I can't figure out how to pass a lambda to such a variadic function. Why I'm interested in converting a generic lambda into an std::function is because I can do the following, but it ends up requiring that I explicitly state the template parameters to std::function which is what I am trying to avoid.

template <typename R, typename...A>
void foo(std::function<R(A...)>) {}
int main() {
    foo(std::function<void()>([](){}));
}


推荐答案

lambda函数对象作为类型 std :: function< T> 的参数,而不明确指定模板参数 T 。模板类型推导尝试将您的lambda函数的类型与 std :: function< T> 匹配,它在这种情况下不能做到 - 这些类型不是相同。模板类型扣除不考虑类型之间的转换。

You can't pass a lambda function object as an argument of type std::function<T> without explicitly specifying the template argument T. Template type deduction tries to match the type of your lambda function to the std::function<T> which it just can't do in this case - these types are not the same. Template type deduction doesn't consider conversions between types.

这是可能的,如果你可以给它一些其他方式来推断类型。你可以通过在 identity 类型中包装函数参数来做到这一点,以便在尝试匹配lambda到 std :: function时不会失败(因为依赖类型只是被类型扣除忽略)和一些其他参数。

It is possible if you can give it some other way to deduce the type. You can do this by wrapping the function argument in an identity type so that it doesn't fail on trying to match the lambda to std::function (because dependent types are just ignored by type deduction) and giving some other arguments.

template <typename T>
struct identity
{
  typedef T type;
};

template <typename... T>
void func(typename identity<std::function<void(T...)>>::type f, T... values) {
  f(values...);
}

int main() {
  func([](int x, int y, int z) { std::cout << (x*y*z) << std::endl; }, 3, 6, 8);
  return 0;
}

这在你的情况下显然没有用,因为你不想

This is obviously not useful in your situation though because you don't want to pass the values until later.

由于您不想指定模板参数,也不想传递可以推导出模板参数的其他参数,编译器将无法推导出您的 std :: function 参数的类型。

Since you don't want to specify the template parameters, nor do you want to pass other arguments from which the template parameters can be deduced, the compiler won't be able to deduce the type of your std::function argument.

这篇关于如何使用模板将lambda转换为std ::函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆