I sympathize with you here. I kind of like the lambda syntax for simple cases in C++, but the complex cases look painful to me, and based on everything else in C++, I predict there are many special cases to remember.
However, if you just want a more conventional syntax for nested functions, you can almost get what you want by placing a static method inside of a local class, and it's available in older versions of C++ too:
If you want it to "close" over your local variables, you'll probably need to actually instantiate an instance of the local class and use a non-static method. Doing this, the capture lists in lambdas almost start to make sense.
Clever. If you let the nesting function have static variables they can be referenced from the nested function too, but actually using lambdas would of course be more clear in practice.
The only feature of lambdas that a proper nested function would miss is the "copy capture".
> The only feature of lambdas that a proper nested function would miss is the "copy capture".
Yeah, reference by default would fit with what people probably expect from other languages, but without a garbage collector (or similar) that's only valid for downward passed functions. Copying allows your nested function to escape the lifetime of the calling function, which might require some other/additional syntax.
Not sure I like implicit capture more than explicit capture but there's [=] if you need it. Also, the return value as the article mentions is optional, so most lambdas look like
const auto nestedfunc = [=](a,b) { /* */ };
Which isn't that much different to me than
{ /* some scope */
function nestedfunc(a,b) { /* */ }
}
const and auto are needed but because it's C++. Beyond that, you have an equals sign which is needed here but [=] which is three characters. Again, small differences, not sure why it looks that much worse.
Now that we know lambdas they are fine, but to answer the question "why is there a book" in the beginning of the thread, it is more or less because it is not as obvious as gcc's c extension.
why [&args...] and not [args...] ? do you really want to capture by reference when you're setting a lambda as a callback ? (likewise in the other direction - tons of arguments for every default, already debated ad nauseam)
I don’t know any other language with lambdas which requires me to spell out explicitly which variables it should close over... so you tell me how Java, Scala, Clojure, Kotlin, Python, JavaScript, Rust, Go, C# and tens of others managed this clearly impossible feat of engineering.
Rust is not really the same as C++ here, you get "the compiler infers how to capture things" as the default behavior, and "take everything by value", which happens with the "move" keyword. We've found that these two cases cover the vast, vast, vast majority of usage, and so C++-style specific capture modifiers aren't necessary. You can emulate C++ style stuff by taking references outside of the closure and using move to capture only the reference.