The idea of having regrets after learning /anything/ in programming is weird.
I agree that the idea or regretting learning something is strange. They probably meant they felt like their time wasn’t wasted.
I think that few people regret actually learning things, but that many regret taking courses or spending time without learning.
I think it’s reasonable to regret learning something based on the opportunity cost. Spending time learning C++ means not spending time learning some other language.
I also think it’s counter-productive to think in terms of regret, and it’s better to think in terms of how to make better choices in the future.
Being in a PhD program, I took my foot off the gas for a month or so last summer to learn some Haskell and Rust. (I tried to learn Haskell the previous year, but it took a few tries to let everything sink in, especially without formal training in type/category theory). I also set aside some time early on reading parts of Clean Code/Code Complete/SICP.
I feel like I delayed my graduation a bit, but I absolutely feel more confident and competent in my ability to computationally decompose and abstract a problem, even if I don’t use all the skills day-to-day.
I did, however, also spend some time lurching through the history of design patterns in C++ before that, which I partially regret–I felt like I was just learning idioms to business-side problems that I haven’t run into, instead of fundamentals that are applicable across domains.
like let me read the source code of a open source software today
To me, this is the most powerful reason to learn C and C++. If you know these languages, you can read the codebases of all the things you use and contribute to them (every browser in existence, every Unix in existence, most user space tools, many GUI tools, many low-level libraries that mobile apps use).
Even if everybody stops writing C/C++ today, you’ll still be using software written in C/C++ for decades.
And of course, that’s a joke – there’s still at least 10x more C/C++ being written every day in the world than any other language that compiles to native code (Rust, Go, etc.)
(repost of HN comment)
I didn’t understand the point of the Rust borrow checker until I started using modern c++.
Could you expound on that?
the Rust borrow checker is effectively compile time move semantic checks – something that C++ doesn’t have.
func2(a); // this is undefined behavior, but the compiler does not catch it
The standard only says that standard library objects (unless otherwise specified) are placed in an “unspecified state” after moving. You can still use the object after moving, e.g. query a size or reassign it. For custom objects, you could do whatever you want (or nothing), so it’s not strictly undefined behavior.
Hence the compiler can’t really complain about it on a per-translation unit level, especially if functions/constructors/assignment operators are forward declared.
A linter should definitely alert about that, though.
Rust puts more constraints on what it means to move an object, so it can more effectively check if a name is bound to live object.
Is there ever a case where you would want to write code like the above?
I’ve run into use-after-move bugs in C++ code, and I think the compiler could have easily caught them and issued a warning (in my case, but not in every case). I expect this to become a commonly-enabled warning in the future.
No! I’ve run into the same bugs :P. I guess if you see func fails in some way, which then puts a back in its previous state, and then call some other function, but that sounds incredibly smelly. It’s probably just this way because lifetimes are handled by scope and they didn’t want to change that too dramatically.
It is not possible to undo the move (unless the moved-to object is a temporary), because the state of the moved-to object was destroyed by the move.
I think I see what you are getting at, though. Since a is a valid object after the move, it is legal in C++ to use a after the move (e.g. replace func2(a) with the invocation of ~MyClass() as a goes out of scope).
So I know it’s impossible to catch every case of use-after-move without flagging some valid code, but I still feel that the compiler can and should warn about some cases (in my case the compiler could have easily proved that the moved-from object held a null pointer and that the member function that was later invoked resulted in UB).
I was watching this Meeting C++ talk and couldn’t help but think of this exchange :P
Oh just wait till you have to deal with other people’s code (i.e. libraries). That’s when the idea of only confining yourself to a nice subset of the language goes out the window :-)