This is a follow up of the discussion found here.
The following code compiles both under gcc and clang (live demo). This is surprising for the case in line //1
Lambdas can "see" a lot of things in their surrounding scope without needing to capture them:
-- Global variables:
int x = 42;
int main() { []{ std::cout << x; }(); }
-- Static local variables:
int main() {
static int x = 42;
constexpr int y = 1337;
[]{ std::cout << x << y; }();
}
-- Functions:
int x() { return 42; }
int main() { []{ std::cout << x(); }(); }
-- Types:
using x = std::integral_constant;
int main() { []{ std::cout << x::value; }(); }
-- Local variables used in unevaluated contexts:
int main() {
int x = 42;
[]{ std::cout << sizeof(x); }();
}
This just naturally falls out of the language rules. You can do the same thing in C++98 with a hand-written callable object:
int main() {
int x = 42;
struct functor {
int operator()() const { return sizeof(x); }
};
std::cout << functor{}();
}
It's unsurprising, as sizeof
does not evaluate its expression:
int main() {
int x; // uninitialized
using y = std::integral_constant; // x used in a constant expression
using z = std::integral_constant;
static_assert(std::is_same::value, "");
std::cout << y::value;
}