In this snippet I am declaring a variable i
inside the lambda's capture.
int main()
{
vector<int> vec;
// Pushing 0-99 numbers to vector
std::generate_n(std::back_inserter(vec), 100, [i = 0]() mutable { return i++; });
return 0;
}
As one can see, there is no type stated anywhere for i
.
As far as I know, I can write the equivalent functionality in this way:
int main()
{
vector<int> vec;
// Pushing 0-99 numbers to vector
std::generate_n(std::back_inserter(vec), 100, [](){
static int i = 0;
return i++; });
return 0;
}
How does the compiler know the type of i
in the first example? Is it deduced from the operation I perform on it (++) ? Does it know that it is int
because of the container?
There are no complaints when compiling with GCC with -std=c++14 and -std=c++17. Nevertheless, if I compile with -std=c++11 I get the following warning:
lambda_test.cpp: In function ‘int main()’:
lambda_test.cpp:24:51: warning: lambda capture initializers only available with -std=c++14 or -std=gnu++14
std::generate_n(std::back_inserter(first), 100, [i = 0]() mutable { return i++; });
^
MORE: Given the comments, I tried to see a difference on what the compiler produces for c++11 and 14, but it generates the same code: https://cppinsights.io/s/43411e6f
As the error says, you must activate C++14 for lambda capture initializer to work since it was added in C++14.
As far as I know, I can write the equivalent functionality in this way:
No, static storage is functionally different. With capture you can copy the lambda and it will copy the state of the captures. With static variables each lambda access the same global.
How does the compiler know the type of i in the first example? Is it deduced from the operation I perform on it (++) ? Does it know that it is int because of the container?
No, since many many types has the ++ operator.
The compiler simply use the initializer to deduce the type. You can see it as if there was a hidden auto
there:
std::generate_n(std::back_inserter(vec), 100, [/* auto */ i = 0]() mutable { return i++; });
The literal 0
is of type int
. So i
is an int
.
You could technically do this too:
std::generate_n(std::back_inserter(vec), 100, [/* auto */ i = 0ull]() mutable { return i++; });
Then i
has the type unsigned long long
, since the literal 0ull
is of that type.