I have encountered a lambda with static variable in the following answer https://stackoverflow.com/a/79631994/2894535 :
EXPECT_CALL(my_mock, foo(_))
.WillRepeatedly(InvokeWithoutArgs([](){
static int counter = 0;
constexpr static std::array<int, 2> values {13, 26};
return values[counter++ % values.size()];
}) );
My first intuition was to comment or edit the answer with a mutable counter instead:
[counter = 0]() mutable { ... }
My logic was that the static one could be unexpectedly shared between different users. For example, if the test was parametrized and the first instantiation called my_mock.foo() odd number of times, then the second one will start from 26 instead of 13.
On the second thought though, since each lambda creates an anonymous functor class, is that actually the case? I believe my confusion boils down to whether entering the same code twice will create a distinct functor with its separate statics, or reuse them.
This can be boiled down to the minimal example:
#include <cstdio>
auto static_lambda() {
return []() { static int i = 0; return i++; }
}
auto mutable_lambda() {
return [i = 0]() mutable { return i++; }
}
int main() {
auto s = static_lambda();
std::printf("%d,", s());
std::printf("%d,", s());
auto s2 = static_lambda();
std::printf("%d,", s2());
std::printf("%d,", s2());
auto m = mutable_lambda();
std::printf("%d,", m());
std::printf("%d,", m());
auto m2 = mutable_lambda();
std::printf("%d,", m2());
std::printf("%d,", m2());
}
I have run this code and see it produces 0,1,2,3,0,1,0,1, meaning my initial intuition was correct, but am honestly still not sure why, for the language lawyer point of view.