Learning C was a blast and I really enjoy reading and writing C code and studying kernel sources.
C++ on the other hand is a fully matured abomination and I want nothing to do with it. Now you can down-vote me into oblivion.
On the other hand, you enjoy your C until you find yourself:
* In macro hell to get something complex done
* With overly long functions and function name prefixes.
* Needing to write something serious and big - requiring libraries of all sorts, and noticing they mostly don't exist.
* Wanting to tell the compiler optimizer things that C can't tell it.
* Needing to compute some things at compile-time.
... and then you start developing a taste for the "abomination".
IMO, macro hell is something you bring upon yourself. I rarely felt the need to abuse the preprocessor in awful ways in order to build something.
* With overly long functions and function name prefixes.
I'm puzzled how you can get in such a situation. Running out of function namespace? How?
* Needing to write something serious and big - requiring libraries of all sorts, and noticing they mostly don't exist.
There are plenty serious and big projects in C and there are _plenty_ of libraries. Also, C++ can be linked with C, so... I fail to see how you don't get the same kind of issues with C++ if there are any.
* Wanting to tell the compiler optimizer things that C can't tell it.
This might be indeed a problem, but... what can you tell it using C++ to the compiler optimizer? I'm not really a C++ guy so, really, do you have more options? I know there are compiler specific pragmas an modifiers in C as well, but does C++ have specific C++ language stuff and not C++ compiler stuff it can set?
* Needing to compute some things at compile-time.
Again... what yould those things be? CRC's? You can do that in C if the compiler allows you as well (gcc and clang do). What else? And what more exactly does C++ bring to the table concerning this?
Honestly, I have to think reaaaal long an hard about things that the C lang doesn't let you do or constrains you. It's one of the most liberating languages, honestly. I work with it day in and day out, so I might be biased, say what you want about C, but not that it's not powerful!
Yes, in several ways, including:
* Move semantics - you can make the compiler aware that some values are "going away" soon and can be cannibalized rather than conserved. * Compile-time execution - a significant (and growing) subset of the language can simply be computed at compile-time rather than run-time. So if you have a certain function which computes something - anything that doesn't involve I/O (and until C++20 - uses a fixed amount of memory), and your inputs are known in advance, the function won't have to run whenever you run the program, but would be removed entirely in favor of the result.
To see how these and other language features combine to allow for highly-efficient code, check out this video:
CppCon 2016: Jason Turner “Rich Code for Tiny Computers: A Simple Commodore 64 Game in C++17” https://www.youtube.com/watch?v=zBkNBP00wJE
Where you write an implementation of the Pong game - with high-level, straightforward code, and no "dirty tricks" - whose compilation result requires exactly 0 stack and 0 heap space.
In C too, functions are removed entirely in favor of the results. This is a quality-of-implementation issue. There are good and bad compilers for most languages. C is less dependent on compiler quality however, with relatively simple compilers being able to produce good output for stylistically typical code.
[0]. https://drewdevault.com/2020/04/15/Status-update.html [1]. https://drewdevault.com/2020/01/04/Slow.html
Rust does not provide the facilities to write libraries with stable ABIs, and C++ libraries have to be written carefully to achieve ABI stability. More precisely, important C++ and Rust language features (templates and generics, respectively) conflict with the ability of providing ABI stability (at least it was thought so... Swift is novel in how it provides ABI stability guarantees for library writers alongside generics).
D as Better C works very well as a replacement. I've converted a lot of code from old C to BetterC and it goes very quickly (once you remove the use of the preprocessor, which can be tricky if you use the preprocessor as a metaprogramming tool). The syntax is nearly identical.
https://dlang.org/blog/2017/08/23/d-as-a-better-c/
Note that no D runtime library is required. Just the C Standard Library.
(Yes, I am in charge of the D Language Foundation. No, I don't receive a nickel from it. I do it because I believe in it.)
I dislike the argument that C++ is great because you can limit yourself to appropriate subset. It becomes a different thing while still being called C++, which is miscommunication. If you can brand your subset as EmbeddedC++ and gain widespread audience, then we're closer to good thing. (except there's lot of embedded happening on Linux boards where "normal" C++ is acceptable)
My frustration mostly comes from working on huge embedded C++ project where each separate corner of codebase used its own subset of language. This brings down complexity and reduces mental overhead locally, but reasoning about the whole system is impossible.
> You still have to learn how exceptions work and why avoid them, what is heap and how to disable it, what are pure virtual classes and so on.
Do you mean later on? As I see it, you do not have to learn about the things you do not use and can concentrate on the basics. Once you are comfortable and need to venture out into projects where other parts of C++ are used, you would need to, of course.
I was pointing out that if you as beginner manage to set correct boundaries for C++, you still need to know what's on the other side in order to avoid it. You've constrained yourself to smaller language (a good thing), but you haven't eliminated all the baggage / mental overhead that rest of C++ brings. The optimal approach would be to pick a language that's already well suited to problem. I would always choose enhanced C over degraded C++.