c++lambdareferencestd-function

Storing a lambda that returns a reference into a std::function


I have some trouble to return a reference from a lambda. This code works :

std::function<int*(int*)> funct;

funct = [](int *i){
    ++*i;
    return i;
};

int j = 0;
std::cout << *funct(&j) << j;

Output : 1 1

But not this one :

std::function<int&(int&)> funct;

funct = [](int &i){
    ++i;
    return i;
};

int j = 0;
std::cout << funct(j) << j;

Building error :

C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\type_traits:1441: error: C2440: 'return': cannot convert from 'int' to 'int &'

Why is this happening?


Solution

  • The lambda deduces the return type as if specified with auto. auto ret = i; would deduce ret to be an int.

    One solution is to explicitly state the return type of the lambda:

    funct = [](int &i) -> int& {
        ++i;
        return i;
    };
    

    As mentioned in the comments another way is

    funct = [](int &i) -> decltype(auto) {
        ++i;
        return i;
    };
    

    which essentially tells the compiler not to do any deduction and to just use the type as if decltype had been used on the return expression.

    If you are curious about the exact rules check the documentation which also has a section on auto and a bit on decltype(auto).