Search code examples
c++c++11lambdarvalue-reference

C++11 lambda can be assigned to std::function with incorrect signature


The following compiles and runs (under Apple LLVM version 6.1.0 and Visual C++ 2015):

#include <functional>
#include <iostream>

struct s { int x; };

int main(int argc, char **argv)
{
    std::function<void (s &&)> f = [](const s &p) { std::cout << p.x; };
    f(s {1});
    return 0;
}

Why doesn't the assignment std::function<void (s &&)> f = [](const s &p) { std::cout << p.x; }; generate an error? A function accepting an rvalue reference should not have the same signature as a function accepting a const lvalue reference, should it? Dropping the const from the lambda's declaration does generate an error as expected.


Solution

  • To expand on the existing comment and answer:

    The point of std::function<R(A...)> is that it can wrap any function or functor that can be called with A... and have the result stored in an R.

    So, for example,

    std::function<int(int)> f = [](long l) { return l; };
    

    is just peachy.

    So what you have to ask yourself when you see something like this: if you have a lambda taking const T &, and you have an expression of type T && (or, more accurately, you have an xvalue of type T), can you use that expression to call the lambda?

    Yes, you can.

    And if you can, then std::function is supposed to be able to store that functor. That's pretty much the main point of std::function.