2

Given the function:

void foo(std::function<void(int, std::uint32_t, unsigned int)>& f)
{
    f(1, 2, 4);
}

Why does this compile:

std::function<void(int a, std::uint32_t b, unsigned int c)> f =
    [] (int a, std::uint32_t b, unsigned int c) -> void
{
    std::cout << a << b << c << '\n';
    return;
};

And this fails to compile:

auto f =
    [] (int a, std::uint32_t b, unsigned int c) -> void
{
    std::cout << a << b << c << '\n';
    return;
};

With the error:

5: error: no matching function for call to 'foo'
    foo(f);
    ^~~
6: note: candidate function not viable: no known conversion from '(lambda at...:9)' to 'std::function<void (int, std::uint32_t, unsigned int)> &' for 1st argument 
void foo(std::function<void(int, std::uint32_t, unsigned int)>& f)
     ^
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
Michael Barker
  • 14,153
  • 4
  • 48
  • 55

1 Answers1

13

A lambda is not a std::function. Thus, calling the foo function requires construction of a temporary std::function object from the lambda, and passing this temporary as an argument. However, the foo function expects a modifiable lvalue of type std::function. Obviously, a prvalue temporary can't be bound by a non-const lvalue reference. Take by value instead:

void foo(std::function<void(int, std::uint32_t, unsigned int)> f)
{
    f(1, 2, 4);
}
Piotr Skotnicki
  • 46,953
  • 7
  • 118
  • 160