Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I pass a lambda to this function which takes a std::function? [duplicate]

Tags:

c++

c++11

lambda

The following program is illegal, and I would like to understand why:

#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's output:

$ 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.

It seems like I ought to be able to convert my lambda to the std::function received by deduce. Why is it not possible for the compiler to apply an appropriate conversion in this case?

like image 882
Jared Hoberock Avatar asked Jan 08 '15 23:01

Jared Hoberock


1 Answers

The problem is that while a lambda that takes an int and returns an int can be converted into a std::function<int(int)>, its type is not std::function<int(int)> but an arbitrary implementation-defined type I think.

You can work around this by telling the compiler what types you want. Then the conversion will happen as expected.

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

Alternatively, be explicit on the static type of f.

std::function<int(int)> f = [](int x){ return x + 1; };
deduce(f);  // now also ok
like image 81
5gon12eder Avatar answered Oct 27 '22 00:10

5gon12eder