为啥我不能将 lambda 传递给这个需要 std::function 的函数? [复制]

Posted

技术标签:

【中文标题】为啥我不能将 lambda 传递给这个需要 std::function 的函数? [复制]【英文标题】:Why can't I pass a lambda to this function which takes a std::function? [duplicate]为什么我不能将 lambda 传递给这个需要 std::function 的函数? [复制] 【发布时间】:2015-01-08 23:01:14 【问题描述】:

以下程序是非法的,我想了解原因:

#include <functional>
#include <iostream>

template<typename Result, typename Arg>
void deduce(std::function<Result(Arg)> f)

  std::cout << "Result: " << typeid(Result).name() << std::endl;
  std::cout << "Arg: " << typeid(Arg).name() << std::endl;



int main()

  auto f = [](int x)
  
    return x + 1;
  ;

  deduce(f);

  return 0;

clang 的输出:

$ clang -std=c++11 test.cpp 
test.cpp:48:3: error: no matching function for call to 'deduce'
  deduce(f);
  ^~~~~~
test.cpp:26:6: note: candidate template ignored: could not match 'function<type-parameter-0-1 (type-parameter-0-0)>' against '<lambda at test.cpp:34:13>'
void deduce(std::function<T2(T1)> f)
     ^
1 error generated.

看来我应该能够将我的 lambda 转换为 deduce 收到的 std::function。为什么在这种情况下编译器无法应用适当的转换?

【问题讨论】:

【参考方案1】:

问题在于,虽然接受int 并返回int 的lambda 可以转换std::function&lt;int(int)&gt;,但它的类型不是 @ 987654324@ 但我认为是任意实现定义的类型。

你可以通过告诉编译器你想要什么类型来解决这个问题。然后转换将按预期发生。

auto f = [](int x) return x + 1; ;
deduce<int, int>(f);  // now ok

或者,明确f 的静态类型。

std::function<int(int)> f = [](int x) return x + 1; ;
deduce(f);  // now also ok

【讨论】:

谢谢。我知道类型不一样,但我试图理解为什么编译器无法在此处应用适当的转换。 问题不是参数值的转换,而是模板参数的推导。一旦它们被知道(如我给出的第一个 sn-p 中),转换就很好了。我将尝试是否可以在此处查找有效的确切规则。 是的,扣分是问题。这必须是一个精确的推论,否则,一切都会发生:任何专业化可能会或可能不会有必要的转换。 lambda 函数的定义并不是完全任意的,为了记录,但答案的要点是正确的。 @Jared,编译器无法构造std::function(这只是一个类模板),但它可以为具体的ResultArg 构造std::function&lt;Result(Arg)&gt;。如果您确实为这些提供了具体类型(例如 5gon12eder 所做的 int 和 int ),那么它有一个构造函数,可用于将您的 lambda 对象转换为该类的实例。但是没有类型,它就没有可以尝试的构造函数,因为它没有类型。而且你不能只是概括地推断这些类型。

以上是关于为啥我不能将 lambda 传递给这个需要 std::function 的函数? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

我不能将 lambda 作为 std::function 传递

为啥我不能在 C++14 的 lambda 中移动 std::unique_ptr?

为啥我们不能通过值传递数组来函数?

为啥我的 std::ref 不能按预期工作?

错误“lambda 不是从 'std::function' 派生的

何时更喜欢 lambda 而不是带有 std::async 的打包任务? [复制]