For example, using C++ 20 ranges over simple loops is an example of where brevity and “cleanliness” can reduce clarity because the heavy templating and operator overloading hides what the code actually does.
On the other hand, sometimes one can’t avoid the complexity when writing a library that aims to work on many platforms, and with special tricks such as SIMD, as is present in the Eigen library.
As does any function call.
What the code using C++ ranges is doing is quite clear, but understanding how it is doing it requires some knowledge of how ranges work.
That stating that is not stating the obvious, shows how screwed we are. Indeed, why use things that are not necessary? "Just because you can"?
And still I find everywhere programs less than 1000 lines of code, that can be written maybe in 10 lines of python, but in C++ they use templates, inheritance, and the most obscure corners of the STL. Mind you, I do not mean some random github repo. where somebody was just practicing and learning. I mean production software, made "professionally"
There are places I have that 1000 line template mess that nobody can understand in less than a month of staring at it (including me and I wrote it!) because it is the right answer. Most of the time I don't write that because it is hard and there is no advantage, but once in a while it is the right answer to a complex problem. Those 1000 lines can turn many many 100 line problems into 5 line problems and so overall be a net reduction when done right.
The longer I write code the less use I have for inheritance. Templates are still useful.
I do use lambdas all the time, they are very powerful and so worth learning the complex syntax to make them work. I strongly recommended you add them to your list of things you use all the time (replacing loops)
I use templates, but only when I'm writing generic code. Templates in the right place can save a lot of code and errors. However they are rarely needed and so you only need a few people on a large project to write them, and everyone else can say "not in my subset of C++, talk to [someone else]"
> more advanced features you use, the easier it is to make subtle mistakes, confuse someone who hasn't seen that feature before,
Also the more people get used to seeing it. Soon everyone knows those things, and so they won't make the subtle mistakes of be confused. Of course you need to pick the right things to add. Ranges look really useful for people who work on a different type of problem from the type I normally work on - thus ranges are not in my subset of C++, but my impression is they should be very common in other areas. Modules are not currently on my list, but everything I know suggests in 5 years the tools will (finally!) work and I will be converting my code to modules. I'm not clear where reflection sits, I suspect like templates a few experts will be needed on a large project and everyone else just uses them - but only time will tell.
This is a great idea in theory, but doesn't always hold up well. With a sufficiently large and old project, and when people move on and off either parts of the code or the entire project regularly...it doesn't hold up as well.
No one may see or touch that code again for years. By the time someone realizes there's a missed edge case or it needs expansion, it may simply be too late. The person that worked on it may be gone completely or haven't worked on that part of the code in those years.
The more advanced features you use, the easier it is to make subtle mistakes, confuse someone who hasn't seen that feature before, or just make everyone working on the software wary of ever touching it.