This is really true. I have worked with C++ for 15/20 years, reading and studying everything I could.
I've reached a good competence but every time I stopped for a while I immediately fell behind.
C++ is a difficult beast.
This is really true. I have worked with C++ for 15/20 years, reading and studying everything I could.
I've reached a good competence but every time I stopped for a while I immediately fell behind.
C++ is a difficult beast.
I will say I still really enjoy the simplicity of C, but the guarantees of Rust are really hard to beat.
Rust has some nice-to-haves of course, but C++ has been able to grow up and evolve because of the rich feature-set the template meta-programming language has provided it.
One can simply stick to C++11 or 14 and work with those features alone to make strides in development. Hell, people have used C++98 for decades.
Personally, I think what C++ offers is the same as Rust. Both need a robust testing and code-coverage tools for correctness, but the end result requires simply good development practices and love for the work being done.
I think this dismisses incidental complexity that can certainly exist in general, and certainly does exist in C++.
Just look at how complex move semantics are in C++:
* you have & and && references,
* there are all sorts of categories (e.g. glvalues),
* in a template && means something different (but not always),
* std::move by itself doesn't actually do anything (yes I know it's a cast but this is still confusing at least upfront),
* even if you do pass the result of std::move (or otherwisie know you have an rvalue reference) to a constructor then it's still possible that the object will actually be copied with no error or even warning.
In Rust, the difference is enormous:
* When you move from a value, it's guaranteed that the old object's destructor will not be called, so you don't need a move constructor that hackily sets up an empty value so is destructor won't do anything;
* Move is always a bitwise copy so it's easier for the caller to understand and free for the implementor to implement (this is enabled by the previous point)
* Move is the default instead of copy which makes a million times more sense because you can just implement copy as a regular method that happens to return (move!) its result (whereas you could never implement move as something that returns its result by copying) and if you actually want to copy a value to a function you can just call the copy method and move that value to it.
This final one is key is really, it's not possible because of C++'s history and backwards-compatibility requirements and that's why it had to come up with the crazy system it now has. Rust has many nice features but really the move vs copy stuff by itself is a huge saving in complexity, and the fact that Rust manages it at all proves that it is not intrinsic to the problem.
(Disclaimer: I have worked with C++ on and off full time for more than 15 years, whereas I have only tinkered with Rust.)
I have worked with C++ for a hell of a lot more than 2 hours since C++11 came out (the first version with move semantics) and worked with many others that have too, and I can tell you that "once you have it you're done" is just not true. I fully understand all the concepts but I can still make mistakes.
These are advanced template techniques for people who want to dive deep into writing template libraries that are as generic as possible. Insinuating that they are a necessity to learn is ridiculous.
decltype is easy and only necessary when trying to make something more generic.
> guaranteed RVO
Also something that programmers don't even need to know exists unless they want to dig into it.
Or landing by parachute on a codebase that needs some work.
Or just having to integrate a C++ library done by other team into their managed language framework.
Ridiculous is how many in ISO C++ seem to ignore Bjarne's plea to not overcomplicate the language.
I pointed out that your criticisms are a huge stretch in reality and instead of confronting that, you decided to ignore what I said and throw more out there that isn't even a part of C++.
https://en.wikipedia.org/wiki/Gish_gallop
Boost is mostly terrible and isn't hard to avoid. People don't need to use it and they don't need to debug it. This is far removed from talking about the language itself.
Should we go through the ISO C++ features that were born in Boost?
Ironically there are probably an endless streams of criticisms that could be lobbed at it, but everything you've mentioned are things that just aren't problems in practice.
Lot's of people read books on Object Oriented programming, and write absolutely awful Java Enterprise code. Or they read books on algorithms, and write fantastically efficient code that's completely unreadable.
And what's better than a book of best-practices? A compiler that enforces them.
Reading books doesn't automatically fix that, but it can help, just by exposing one to practices that one might not have come across in the kind of work that passes for programming for mathematicians, data scientist, etc.
That's probably fair! There was a programming module in my degree, and it was awful. People were literally rote-memorising whole scripts for the exam (the CS department at my uni didn't do exams, but of course the maths dept did for their programming module).
I actually started programming before the maths degree, and have over 10 years of experience at this point. I'm not saying my code is perfect, but I imagine I'm incorporating many of what you would consider best practices.
I guess reading books can help. I've just not actually met any developers who write high quality code who learnt it from a book. They all learnt it from 1. Practice and experience 2. Colleagues in a work environment 3. Places like HN, which is excellent at exposing you to things you might not otherwise have come across.
I guess my criticism of C++ is over all the little details that can trip you up if you don't have a comprehensive knowledge of the language (undefined behaviour, use after free, etc). Most of them aren't tooo bad on their own, but there are just so many. Most other languages simply don't have these issues.
My original point was not that you can never understand move semantics, or that you can never write decent C++ programs. I've written a few complex C++ programs used in production that are pretty nifty if I don't say so myself! I was also not trying to say that it's unreasonable to have to read books about programming languages, that's pretty silly in my view.
What I was actually saying is that move semantics - and other features, that was just an example - are harder than they need to be in C++. Even once you've understood the feature, it still requires a constant mental burden - more to the point, more mental resources than it potentially could - and we all have finite mental resources. I had actually quoted the wrong part of your original comment, I had meant to quote this:
> I think to get good at a given systems language these days the effort is the same.
This is what I really disagree with, especially if you include not just C++ and Rust but other current and even hypothetical future systems languages. I'm not even saying that Rust is necessarily a better language than C++; I've not used it enough to know that. Just that, for that one language feature at least, Rust shows that it is possible to create a language with move semantics that are both easier conceptually and more ergonomic to use - it's a total win-win. For other language features, perhaps other languages show how it could be done more simply. There is definitely scope for systems languages that require less effort to learn and less effort to use after you've mastered them. (Rust may or may not be one.)
u/yosefk is probably the greatest CPP basher of all time.
iirc, Rich Hickey was an expert CPP programmer before he developed clojure.
Someone who has been proficient at something for a long time has a very difficult time getting into a mindset of a beginner. This is why I think you are completely wrong about this point.
> Rust has some nice-to-haves of course, but C++ has been able to grow up and evolve because of the rich feature-set the template meta-programming language has provided it.
C++ has not and can not hide all the hidden gotchas and complexities that it has accrued over the years.
But Rust will catch data race mistakes at compile time, which is very nice. That is a common mistake, and a mistake that can keep happening without you being aware for a long time.
It only applies to threaded code, as soon as IPC, or other kind of external resources enter into the picture there is very little that Rust's type system can do to help with.
Just because this doesn't extend to IPC (of course not) doesn't mean there is some kind of misconception here.
> so anyone without experience in distributed computing assumes guarantees that Rust actually does not provide.
[citation needed]
I see this pretty often and don't understand where this idea originates from. We have huge amounts of evidence to the contrary[1], that is generated by developers who likely have more experience with parallelism and memory than anyone in this comments section ("likely"). If the ultimate pedigree don't get it right, keeping in mind that they never have (apart from NASA who disallow threading and allocation), how is there this belief that it is at all possible.
It's the software equivalent of flat-earthing or climate change denial. We have abundant hard evidence supporting the inability for humans to reason about memory allocation, and absolutely zero evidence to the contrary.
Safe Rust eliminates entire categories of bugs. It doesn't eliminate all bugs (including vulnerabilities), so you do need testing, but it does a huge amount more than nothing (C++).
I think there's space for a language that is less, and is "done". When it's announced on this website, the comments will be "so it's Rust without X, or Kotlin without Y", but those comments will be in the same vein as "why not use rsync" and "less space than a nomad".
I bet that many people won't like it and will stay on Java 7 forever.