FWIW, I use C++, not Rust or Swift, and I have a fair amount of knowledge and experience vested in it, but I think these questions are worth asking.
I think 'hate' really represent the mind of some people (even if they are a minority) but even if we ignore this extreme, the level of irrationality in technical discussions is generally quite high. You need to have rational people to have a rational discussion. The sad reality is that a lot of technical discussions are only superficially rational and are often a political play to assert superiority on other people (it's true for languages, frameworks, code editors, methodologies, etc ... ).
Meanwhile the Firefox rewrite, the premium example of what they propose is still plodding along and Mozilla PR blogs aside, Firefox is still plugging vulnerabilities in each release and will be for the foreseeable future.
Now let's look at the Swift community... do we have blog posts from them every week about how awesome Swift is and why one should rewrite their working C and C++ code in Swift? No, they keep doing their thing, Swift is becoming better at cross platform, it's also getting some support for machine learning.
That's how one grows a language, through building successful projects, staying positive (and having an entire platform behind it). Not through doomsday scenarios and a constant barrage of criticism.
This is exactly what the Rust community is doing! RIIR is something that's only really insisted on for relatively small pieces of security-critical code. With huge codebases like Firefox the rewrite is done piecemeal, to put the rewritten code in use as quickly as possible. The "doomsday scenario" talk about memory-unsafe languages does not come from people writing Rust, it mostly comes from the security community, even at places like Microsoft - because guess what, they've literally been running around with their hair on fire for decades, and they're sick of this especially now that something like Rust is available!
And C++ can't really truly fix them without breaking backwards compatibility with all the legacy C++ and C code, which is its main selling point.
There are other serious attempts (D, Swift, Go) which the Rust community likes to dismiss for various reasons, but at least two of them are currently much more successful than Rust. They don't have to be 100% in the same niche to take a bite of marketshare.
Even if C++ breaks backwards compatibility in some ways, it will still have better backwards compatibility to itself and C than Rust or any other language. This break could be something as radical as a C++ "unsafe", or it could be clang's -Wlifetimes, or something else. Credit's due to Rust here for pushing some parts of the C++ community to search for solutions.
For D and Go, having a GC immediately puts them outside of that niche. For Go, I would also add all the FFI weirdness due to its weird stack discipline, which means that it is non-zero-overhead when interacting with non-Go code - a fatal omission for any contender for a low-level systems language.
Swift is much closer to the metal, and I would consider it a serious contender if it was pushed on all platforms. But it seems that Apple is not interested in its use outside of their ecosystem, which constrains its effective niche to be much narrower than C++ or Rust, ironically.
And yes, of course C++ is always going to have better backwards compatibility. If it didn't, it wouldn't be C++. But its ability to fix issues is directly correlated with that compatibility - it's a dial where you can have more of one and less of the other, as you choose, but you can't have both. Rust (and Swift) can fix more problems, or can fix problems in better ways, because they are not so constrained.
Conversely, if C++ were to introduce safe-by-default, and require explicit opt-in into unsafe - with all present code being considered unsafe - then what you have is a new language that just happens to embed C++ for compatibility reasons. At that point you might as well fix the syntax warts etc as well in that new safe language, since it breaks everything anyway.
As Rust (or another language with similar safety/performance properties) matures and its ecosystem grows, C++ will increasingly become a language of tiny niches and legacy codebases.
In other words: C++ is the new Fortran.
Which makes Rust the new... APL?
I think the analogy is pretty apt as far as it goes. Fortran by the 70's was a crufty language with a bunch of legacy mistakes that remained very popular and very useful and would continue to see active use for decades to come.
And everyone knew that. And everyone had their own idea about the great new language that was "clearly" going to replace Fortran. And pretty much everyone was wrong. The language that did (C) was one no one saw coming and frankly one that didn't even try to fix a lot of the stuff that everyone was sure was broken.
For myself, I despair that Rust has already jumped the proverbial shark. It's complexity is just too severe, the only people who really love Rust are the people writing Rust libraries and toolchains, and not the workaday hackers who are needed to turn it into a truly successful platform.
As a work-a-day hacker it’s completely become my go to language when I’m writing tools, libraries or just want to knock out a simple algorithm to prove myself right or wrong.
See... I don't think that's true, and argue the huge body of C++ code and talent in the ecosystem is an existence proof to the contrary.
I mean, sure, C++ has its crazy edge cases and its odd notions. But you don't need to understand the vagaries of undefined behavior, or the RVO, or move semantics to write and deploy perfectly sensible code. Literally hundreds of thousands of people are doing this every day.
Now, that may not be a convincing argument about the value of that code. But it's absolutely an argument about the utility of the language in aggregate.
I'll be frank: probably 40% of professional C++ programmers aren't going to be able to pick up Rust and be productive in it, at all. And at the end of the day a language for The Elite isn't really going to mean much. We've had plenty of those. Rust is the new APL, like I said.
Just off the top of my head, std::move doesn't... move [1]. It just returns an, I kid you not "static_cast<typename remove_reference<T>::type&&>(t)" without doing... anything. You can keep on using the old value probably, silently, until out of the blue, it stops working one day. Then you're super, duper sad. Even modern language features are, I don't want to say lies, but "hopes and dreams" the compiler can't enforce. It's like if you really wished C++ had Rust's features, but you can't without breaking things, so you give it your best shot, which ends up just creating yet more complexity.
Rust's answer is...
let x = Value::new();
let y = x;
let z = x; (COMPILER ERROR: X GOT MOVED INTO Y)
C++'s modern features are to Rust's equivalents what the ruined fresco [2] was to the original. If you stand far enough back, it's basically right. If you get up close it's hilariously and trivially broken.It takes a lot of gymnastics to call this language approachable or understandable. It's basically a coal powered car made of foot-guns. That doesn't mean it's not a car, or that it won't get you where you're trying to go, I'm just saying it's an open question how many pieces you'll arrive in.
[1] http://yacoder.guru/blog/2015/03/14/cpp-curiosities-std-move...
[2] https://www.npr.org/sections/thetwo-way/2012/09/20/161466361...
I mean that makes sense in a (somewhat nonsensical) way, std::move is a marker for "you can move this thing if you want".
The much weirder part is that even if a value is moved it's not moved, it's carved out, you get to keep a shell value in a "valid but unspecified state". Reusing that value (which the compiler won't prevent) may or may not be UB depending on the exact nature of the operation and state.
Oh and of course that a change / override to the caller and recompile can change the behaviour of the callsite entirely (e.g. a previously moved value is not moved anymore, or the other way around) but that's pretty common for C++.
Don't you kind of have to though? These invariants are in your code no matter what, in the case of Rust they are checked by the compiler (you don't necessarily have to understand every nuance, because it's checked for you), in C++ they aren't checked and are a potential bomb waiting to go off.
> Empowering everyone to build reliable and efficient software.
The language is entirely about inclusion, empowerment, and removing the fear of systems development.
I know you're trying to compare it to APL as that language mostly died off and is thus obscure, but I think the analogy is a little off.
While APL is weird, it is actually really easy for me (someone with less than 15 hours playing with the language in total over the past few years) to code up some basic scripts a lot easier than something like C++.
I'm being absolutely serious too. C++ is pretty low level and as a Python coder I feel like I'm sinking in quicksand with everything required to do something simple. APL is basically built around passing arrays of numbers or strings to weird symbols that operate on the whole array. This means I can do text processing with only a few symbols and a library function (and all interactively) where C++ requires lots of boilerplate and debuggers and compilation and pointers. In short, APL seems to be a lot less complicated than both Rust and C++ in my opinion and most using it have very little formal programming experience and have no problem picking it up from what I've read.
I know what you were essentially trying to say though.
And yes, Fortran, APL, Ada (also Modula-2 & Oberon, Smalltalk and a bunch of other forgotten languages presented as the Next Big Thing at the time) are all uniformly simpler than either C++ or Rust. The modern world is a more complicated place and programming tools have kept up.
Looks to me more like proof that C++ has been around a long time
But it doesn't mean that we can't do it better these days.
Well, a certain number of professional programmers are past the point of being willing to learn new technologies, so maybe that's true. But close to 100% of the people who might become professional C++ programmers could instead become professional Rust programmers.
Rust could easily go the same way.
But, C/C++ is the best option for us for high-performance network processing. We're dabbling with Rust for small applications where we would use Python previously and it's working pretty well -- but there's no way we could use Rust for the core application yet. Modern C++ has really grown on me and it's sometimes a love/hate relationship but totally a huge improvement over ancient C++ or C.
I think the article maybe doesn't do enough to outline the full extent of the problem by focussing on a few counterintuitive cases that are present in C++17, because you're right, all of those cases in the article are ones that can be learned and remembered without issue. The real problem, as I see it, is actually that the core language semantics mean that there's no foreseeable end to the foot-shooting treadmill. Since the language is fundamentally permissive of such things, it's likely that further spec revisions will introduce abstractions like string_view that are easy to use unsafely, aren't flagged by static analysis tools, and end up in security-critical code.
Because this feels like a necessary disclaimer, I don't think that fact justifies migrating every active C++ codebase out there to Rust or anything, since pragmatically speaking there are a lot more factors beyond just core language semantics that go into evaluating the best choice of implementation language. I guess my takeaway is neatly expressed by the post title: there's a sense that I get from C++ users (granted, maybe only naive ones) that sticking to the features and abstractions introduced in C++11/14/17/etc basically eliminates all of the potholes of old, and it's evident that that's not true and will probably continue to be not true.
I'd love to hear more information on this! In my mental model, you could just use Go to replace your Python utilities, but Rust might be workable for your core (or at least its designers would like it to be and would like to know why it isn't).
So the biggest challenge with moving to another language is reproducing the same low latency and high performance we've carefully designed in C++ to a Rust analogue... which given we haven't really used Rust enough yet to have a total sense of this, is hard.
In the long future, I can see Rust working in gradual stages -- but of course focusing on biz objectives is better first when we know how to write high perf C++, hence spending time to play with Rust on side tooling or other smaller projects.
From what little Rust I've written so far I really do like it, so hoping that I can incorporate it more
Hopefully that stuff will be helped with things like Language Server Protocol and Debug Adapter Protocol.
C++ isn't going anywhere. In 20 years you may not be writing in it, but you'll still be calling into it somewhere in the software stack (especially if things continue moving the WebAssembly direction).
Even if you're using Python's SciPy today, you're calling into LAPACK written into Fortran.
Yet, C++ is still there as the binding layer between UI and GPGPU.
Rust is also a good language. Trash-talking C++ does no one any good.
Overwhelmingly, the substantial gains to be made are moving people off of C. Every other possible benefit is a rounding error. It is still much easier to get people to C++. Once dislodged, they might continue on to Rust, or br seduced by C++'s greater expressive power and more powerful libraries. Either way the world will be better.
C++ today seems weighed down by legacy cruft, compared to Rust, but Rust is rapidly accumulating its own legacy cruft. By the time it is mature it will have easily as much of its own.
I do see many of the advantages of both Rust and C++, but one of the reasons I like C is its relative simplicity. I only did a single small thing in Rust to try it out, and while still quite complex, at least it felt more manageable than C++ once you understood the borrow checker. The big elephant in the room however is Go. Every time I started something and would consider Rust, it ended up being 'why not just Go?'.
At least for me, it was much better suited language to be moving to coming from a C background. The biggest initial hurdle was setting up the dev environment with the completely backward GOPATH and GODIR environment variables - which just feels absolutely wrong (although this now in the process of being addressed). The language itself however was an absolute breeze, I felt right at home. Simple, quick, straight-forward, with tons of libraries and tools for my current field of work, coupled with performance more than acceptable for 99% of the applications I need and static binaries which are easily deployed anywhere, also eliminating a ton of complexity. Is it perfect? No, but what language is? But if you want to convince C-programmers to ditch C for a memory-safe language - Go is imho in many cases a much better option to move to.
There's a deeper debate lying at the heart of the Rust-vs-C++ conversation (it's the same one at the heart of Haskell-vs-Lisp), which is really about expressive freedom vs. the strategic usage of constraints. That debate will, truly, outlive all of us. You can probably guess which side I'm biased towards; I won't lay it all out here.
Since you cannot use these powerful libraries, you are (if you like) "constrained" to write fragile code at what would have been the call site.
Each use of a powerful library eliminates all the bugs that would have come from not using one. Those are bugs that Rust designers have elected to keep, in exchange for the memory-use bugs that we largely eliminate, in C++ code, by reliance on powerful libraries.
Powerful libraries eliminate many, many more bugs besides memory misuse.
I can give an example of the opposite: language-aware macros. No amount of C++ TMP hackery can approach a well-designed Rust DSL.
Ideally, can you give a concrete example of some abstraction that can be implemented in C++ with templates, but not in Rust with generics and/or macros?
Can you be more specific? I don't even know what you mean by "powerful library". If you mean a library that's been developed and debugged for a long time, then sure, C++ currently has the advantage there, but that's a transient state and nonspecific to the language itself. If you mean a library that does wild, earth-moving things then I would call that a liability, not an advantage. The language features that allow such things are sources of bugs that Rust designers have elected not to introduce in the first place.
The question of, "In April 2019, which language and ecosystem are more reliable?" is a perfectly valid one. Stronger language semantics vs decades of library refinement. It's not at all obvious. But the answer to "Is Rust or C++ a better language in the long run?" seems clear to me.
I see, too, that there are plans for some support for generics in the near future. So the answer might become yes, in time.
Then, you have the cognitive overhead of translating the documentation, and other sample code. In my experience with bindings, this ends up requiring knowledge of the language you're binding to. It seems easier to just write it in the native language instead and deal with those quirks rather than bindings quirks.
Do the Rust bindings show the Qt docs in the autocomplete? If there's not input validation on the binding side, then you'll end up in C++ again figuring out how to sort things out.
Regarding CUDA, I think we're all hoping for a cross GPU alternative. There's OpenCL, Sycl, ROCm, Kokkos but their API is also written in (you guessed it) C++. Need to render to OpenGL? You'll be writing in C. Unless one of the companies decides to replace driver interfaces with Rust, any application using them will be dependent on N bindings working.
You're ultimately not escaping C/C++ for any systems development. You either deal with the complexity of interfacing between language A and C/C++ or just deal with the quirks of C/C++ themselves. Pick your poison.
https://github.com/KDE/rust-qt-binding-generator
> You're ultimately not escaping C/C++ for any systems development.
We eventually should. C/C++ should retire even for drivers and kernels. But for now there is still a lot of baggage to deal with indeed.
I’ve done a fair bit of mixed Rust + CUDA C++ though, and found it to be a very nice way to build high performance code with safe high-level interfaces that someone can grab and use with little to no understanding of GPU architectures. It’s even pretty straightforward to build wrapper types that leverage Rust’s ownership system to track lifetimes and safe management of device buffers as well (unfortunately I can’t release that code but it really was pretty simple so hopefully someone else will soon do it openly, or by now maybe someone already has)
Either way, C++ is certainly not for every project, but the articles scattered around the web claiming it should be superseded by Rust are plentiful. These opinion pieces make no attempt to credit C++ for when it does make sense to use. Despite it's quirks, it is still the most optimal way to program HPC applications or cross platform GUIs that are not Electron based. The security tools around it and the fact that it's an ISO standard language make it a solid choice for many enterprises.