So it's not that we aren't getting features. They are coming quite fast and people regularly complain that new C++ has too many things for them to learn and keep up with. The issue is that those are the same features everyone has been asking for for over a decade so the people that really care found workarounds and eventually move over to the new std way of doing things when they can while everyone else continues waiting for that one feature they really care about.
I think the committee is focused on the wrong things
Quite the opposite. Proliferating the language itself with ad-hoc constructs would be shoe-horning.
In fact the truth is the people working on C++ don't actually value fast compile times over other matters (fast runtime, ABI compatibility, etc.)
They say they do. But they don't in their actions.
One egregious example: look at the compilation speeds of clang with release build configs (-O2 or higher, etc.) over the years.
It compiles much slower now than it did in 2014 for the same code. The compilation speed is worsening at a much faster rate than the runtime speeds are improving from version to version.
This is especially true for library features where users can always use third party libraries for containers/algorithms that are yet to be standardized (or indifinitely - not everything should be added to the stdlib). But even language features can and should exist as compiler extensions before we are stuck with them.
One nice advantage of static reflection, macros and other form of program synthesis is that you can experiment with new syntax as a library before committing to integrating it to the base language.
Care to point an example?
- export templates is the canonical one.
- Universal references are a great feature in principle, but the way they are integrated in the language is far from ideal.
- Both features are great in isolation, but the interaction between initializer lists and aggregate initialization is a giant footgun.
- Coroutines are overly complex and still incomplete but I still have hope.
- Modules feel DOA so far.
- Unrestricted compile time evaluation is great, but the constexpr qualifier per se doesn't guarantee any useful property.
edit: overall I'm happy with the evolution of the language, but the standardization process has flaws
Or stopped writing C++, I'd consider myself one of these for many use cases I used to use it for.
Some use cases like GUI programming sound like they are better addressed by specialized tech stacks. Nevertheless, either you're talking about greenfield projects or you are hard pressed to find a justification to rewrite a project in another framework. Claiming you stopped writing C++ doesn't fit the bulk of the experience of anyone maintaining C++ projects.
I never got this. Can't you just decide to use subset of the language? No-one forces people to use every single feature. It's okay to use C++ like "C with classes" and occasionally cool new thing, when it is right tool for the job. Only people where this argument is truly valid are compiler/tools people.
No, you can't. Not in the long run, at least. You will have to use libraries that have chosen a different subset, new people will join your team, things will get sloppy as the company grows, etc. Committing to a subset of the language is not free, it's hard and it's a lot of work. And for what?
That is harder than it sounds. First you have to select which subset to use, it is almost impossible to get any two engineers to agree on that - if you do get agreement that is a bad sign - generally it means the people in the room don't know C++ well enough to make the decision and so you choose the wrong one. The best you can hope for is a compromise where nobody is happy - and thus everyone will look for an excuse to bring in their pet part of C++ not in the subset because there is a "good reason" for an exception.
Even if you select a subset it is almost impossible to enforce whatever subset because even if you don't allow your people to use it directly odds are you bring in a third party library that does use it (the C++ standard library being the big one!)
There are a few exceptions to the above. No exceptions/no RTTI are commonly disabled exceptions and so you will get some compiler and library support. Game companies commonly write their own standard library. Both of these are done for performance reasons and have specific domain specific reasons that can be validated in a profiler to set their rules.
Not related to reflection, but C++26 is also likely to get profiles which will disable specific old constructs, (new/delete) which are proven to be error prone and thus result in security issues. These are a good subset to use, but it is about security and so mostly doesn't get the types of subsets you are talking about.
Plenty of the modern C++ people already do this by enforcing things like "no raw loops", "no raw pointers", or "no raw synchronization primitives" during code review.
The issue is that it's a lot harder to justify avoiding new features than it is to justify avoiding old features unless you have a tooling specific reason (ex lack of support) to do so.
However that opinion is kind of a minority. There are a lot of people in the community who don't want to have to learn new features just because a dependency happens to use/expose them. I don't personally see the issue with it.
I'd rather learn std features any day over non-std features. It's just a better use of my time because they work everywhere and someday I might need them. However again not everyone shares this opinion.
If you're writing library code that someone else might use, you don't have much need to understand the features you don't use, unless you have to handle them at the interface. If you're debugging your own code, you really shouldn't have to understand features that you didn't use. (Mostly - see the next paragraph.)
You did say "intentionally". You could wind up using a feature unintentionally, but it's not very common, because most of the new features are either in a new library (which you have to explicitly call), or a new syntax. There are definitely exceptions - I could easily see you using a move constructor without meaning to.
Maintaining someone else's code... yeah. You have to understand whatever they used, whether or not it made any sense for them to use.
Since the proposals target problems with differing philosophies, they each have different traps in them from bad time complexity to outright unrefined behavior. Keeping up with the updates hard because of this.
I think many C++ projects are (or will be) basically infeasible to maintain not because of the old problems but due to the exploding complexity of the interactions of all features, unless developers actively ban using large parts of the language.
I don't really see this as true. In my experience most C++ features actually "just work" together and there are relatively few footguns involved in mixing features.
And it's less that C++ is a patchwork language and more that it is multi-paradigm and multi-discipline. Some features have specific applications and they get used inappropriately but in my experience that is solved with a quick reference/citation of the standard during code review or in a new ticket.