I've been following the development of C++0x from the side-lines and had recently come across an excuse to get back into C++ (developing games).
I recently wrote about using smart-pointers to wrap resources acquired from C libraries. I was able to load textures that I could freely share through-out a tonne of procedural code and know that there would be no memory leaks. Having such implicit run-time support goes against the C philosophy but I think that with smart-pointers there is finally a good defence for breaking that rule.
http://agentultra.com/sdl-and-modern-c-plus-plus-images.html
Other stuff is mostly about fixing bugs in the standard (<cough> rvalue references </cough>), cleaning up the syntax (auto) or providing new syntax for useful but comparatively rare operations (lambdas). That's all good, but initializer lists can change the paradigm of how the code is presented, and that's better.
I think it is rare just because people is not used to it, once they discover the flexibility of lambdas functions you would start seeing them more often (even abuse of them)
I am remaking a event system that I did for a turn based card game and the use of lambdas is just so natural that I realized now how painful and weak was the previous code.
Other than node.js, virtually none of them make regular use of them. When they do, it's mostly just to have a convenient way of passing a callback.
Lambda's are good. But as implemented in C++11 they really don't do anything to change the nature of the code being written. On the other hand, proper use of initializers does, by virtue of not having to write a thousand setXXX() functions, etc...
I disagree with that statement. To the best of my knowledge, lambdas functions are implemented as functors which are created by the compiler. So to have a comparable code you have to create those functors by hand. Which can be a lot of repetitive and boring work if you are doing something like an event system.
"virtually all major languages (other than C and C++03) have some form of straightforward anonymous function"
What about Java? :)
"virtually none of them make regular use of them. When they do, it's mostly just to have a convenient way of passing a callback."
Coming from Scheme (which yeah we can argue whether is a major language or not) I can see a lot of benefits of using closures, way more than just a convenient way to pass a callback.
"Lambda's are good. But as implemented in C++11 they really don't do anything to change the nature of the code being written."
Even when is not as powerful as the implementation in other languages still is a huge gain rather not having them at all. If you use them accordingly you would found a more concise and clear code in comparison with not using them. At least that was my personal experience.
(Yes, I say "will" - I'm not yet working on something that lets me use C++11 features. Sigh.)
Sadly I am stuck in JVM/.NET on the day job.
Rvalue references/move semantics: being able to explicitly express ownership with std::unique_ptr<T> and moving ownership with std::move() has made correct code so much easier to write (especially with unique_ptrs in containers). I don't ever use the delete operator anymore, yet my code leaks no memory and doesn't have the overhead of reference counting or garbage collection.
Variadic templates: these have made templates so much more useful. I've been able to write amazing helper functions that take an arbitrary number of arguments of any types, such as concat_string() [1], which is probably the most useful helper function I've ever written. I've also done some pretty far-out template meta-programming which I'm slightly embarrassed to talk about.
I was surprised by how useful move semantics were, unsurprised by variadic templates, but also surprised that lambdas weren't as significant as I had expected. They're very useful but haven't transformed the way I write code, perhaps because my C++ code was already pretty functional before C++11. Also lately I've been annoyed with lambdas because it's not possible to move an object into a closure, putting them in conflict with my beloved move semantics.
OTOH, having local functions with upvalues was a benefit of lambdas I hadn't even originally considered, but that I've found myself delighting in.
For frequently recurring patterns like "return o.bar" you can write a templated helper function that returns a functor which you can use like this:
getmem(&FooObject::bar)
It's longer than the C# version but shorter than the lambda and easier to type because your editor can auto-complete most of it (unlike the lambda which has a lot of syntax). It becomes even shorter than the lambda if FooObject needs to be const.I use this technique a lot. For instance I can do:
std::sort(people.begin(), people.end(), compare_by_member(&Person::last_name))
to sort a container of Persons by last_name. I've been doing that since long before C++11 and still prefer it over lambdas because it's shorter, easier to type, and clearer when read.Here's the code for compare_by_member if anyone's curious: https://gist.github.com/anonymous/5163229