Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 lambda returning reference

Tags:

c++

c++11

lambda

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.

like image 385
NiHoT Avatar asked Sep 26 '17 15:09

NiHoT


People also ask

Can lambda statements return a value?

The lambda must contain the same number of parameters as the delegate type. Each input parameter in the lambda must be implicitly convertible to its corresponding delegate parameter. The return value of the lambda (if any) must be implicitly convertible to the delegate's return type.

What is Lambda Expression in C++11?

C++11 introduces lambdas allow you to write an inline, anonymous functor to replace the struct f . For small simple examples this can be cleaner to read (it keeps everything in one place) and potentially simpler to maintain, for example in the simplest form: void func3(std::vector<int>& v) { std::for_each(v.

What is lambda return type?

The return type of a lambda expression is automatically deduced. You don't have to use the auto keyword unless you specify a trailing-return-type. The trailing-return-type resembles the return-type part of an ordinary function or member function.

Can a lambda closure be used to create a C++11 thread?

Can you create a C++11 thread with a lambda closure that takes a bunch of arguments? Yes – just like the previous case, you can pass the arguments needed by the lambda closure to the thread constructor.


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

like image 147
nwp Avatar answered Sep 28 '22 02:09

nwp