为什么我不能将lambda传递给这个带有std :: function的函数?

Jar*_*ock 11 c++ lambda c++11

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

#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;
}
Run Code Online (Sandbox Code Playgroud)

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.
Run Code Online (Sandbox Code Playgroud)

似乎我应该能够将我的lambda转换为std::function收到的lambda deduce.为什么编译器在这种情况下不可能应用适当的转换?

5go*_*der 8

问题是虽然一个lambda接受int并返回一个int可以转换为a std::function<int(int)>,但它的类型不是 std::function<int(int)>我认为的任意实现定义类型.

您可以通过告诉编译器您想要的类型来解决此问题.然后转换将按预期发生.

auto f = [](int x){ return x + 1; };
deduce<int, int>(f);  // now ok
Run Code Online (Sandbox Code Playgroud)

或者,明确静态类型f.

std::function<int(int)> f = [](int x){ return x + 1; };
deduce(f);  // now also ok
Run Code Online (Sandbox Code Playgroud)

  • 问题不在于参数值的转换,而在于模板参数的推导.一旦知道(如我给出的第一个片段),转换就可以了.我会尝试是否可以查看此处生效的确切规则. (2认同)
  • 对于记录,lambda函数的定义并不完全是任意的,但答案的要点是正确的.@Jared,编译器不能构造`std :: function`(这只是一个类模板),但它可以为具体的`Result`和`Arg`构造一个`std :: function <Result(Arg)>`.如果你确实为这些提供了具体的类型(比如5gon12eder那样的int和int),那么它有一个构造函数可以用来将你的lambda对象转换为类的实例.但是没有类型,它没有可以尝试的构造函数,因为它没有类型.而且你不能一般地推断出这些类型. (2认同)