Michael Barker
Michael Barker

Reputation: 14378

Why does auto not work with some lambdas

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)
     ^

Upvotes: 2

Views: 330

Answers (1)

Piotr Skotnicki
Piotr Skotnicki

Reputation: 48457

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);
}

Upvotes: 13

Related Questions