Consider the following example:
#include
int main() {
const int m = 42;
[] { m; }(); // OK
const int n = std::rand();
[] {
Its because it is a constant expression, the compiler treats is as if it were [] { 42; }();
The rule in [expr.prim.lambda] is:
If a lambda-expression or an instantiation of the function call operator template of a generic lambda odr-uses (3.2) this or a variable with automatic storage duration from its reaching scope, that entity shall be captured by the lambda-expression.
Here a quote from the standard [basic.def.odr]:
A variable x whose name appears as a potentially-evaluated expression ex is odr-used unless applying the lvalue-to-rvalue conversion to x yields a constant expression (...) or e is a discarded-value expression.
(Removed not so important part to keep it short)
My simple understanding is: the compiler knows that m is constant at compile-time, whereas n will change at run-time and therefore n has to be captured. n would be odr-used, because you have to actually take a look at what is inside n at run time. In other words the fact that "there can be only one" definition of n is relevant.
This is from a comment by M.M:
m is a constant expression because it's a const automatic variable with constant expression initializer, but n is not a constant expression because its initializer was not a constant expression. This is covered in [expr.const]/2.7. The constant expression is not ODR-used, according to first sentence of [basic.def.odr]/3
See here for a demo.