C++11 lambda returning reference

Viewed 3707

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;
LOG<<*funct(&j)<<j;

Output : 1 1

But not this one :

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

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

int j = 0;
LOG<<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 &'

Any idea why? For me it is the same thing.

1 Answers

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

Related