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

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

问题描述

基本上,我希望能够做的是使用任意数量的任意类型参数的 lambda 并将其转换为 std::function.我尝试了以下方法,但都不起作用.

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.

正如评论中提到的,我尝试这样做的原因是因为我试图使用可变参数模板在 C++ 中实现柯里化.不幸的是,这在使用 lambda 时会失败.例如,我可以使用函数指针传递一个标准函数.

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::function 感兴趣是因为我可以执行以下操作,但最终要求我将模板参数显式声明为 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.模板类型推导尝试将您的 lambda 函数的类型与 std::function 匹配,在这种情况下它无法做到 - 这些类型不相同.模板类型推导不考虑类型之间的转换.

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::function的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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