C++ can do all that rust does?

So Stroustrup in various interviews mentions that "modern C++" can do everything Rust does. I have never been a C++ programmer and have no idea about that language - but very curious to find out what is C++ equivalent of Rust's concept of lifetimes and borrow checker. Any pointers will be appreciated!

2 Likes

They're both Turing complete, so he's not wrong. :wink:

10 Likes

Lifetimes and borrow checker doesn't allow you to do something. Instead, it prevents you do certain things like dangling reference access. Sure, C++ can do everything Rust does, and more since there's no restrictions.

15 Likes

Could you please give a citation and exact not-out-of-context-quote of what he said? He might mean something different than what you might expect. There are a lot of ways to interpret what he said. Some are mundane. Some are surprising. Some are nuanced.

26 Likes

Of course Rust can relax those restrictions through unsafe, so saying Rust can't do them is technically incorrect. Safe Rust protects you from lots of mistakes that would be easy to make in another language.

2 Likes

Do you have any links to those interviews. It would be nice to know exactly what he did say.

Having used C++ for many years, as far as I can tell it has a very limited notion of lifetimes. Things like unique_ptr and shared_ptr are useful in that respect though.

C++ does very little to prevent the programmer making mistakes re: object lifetimes. As you will see if you watch presentations at C++ conferences like CPPCON: https://www.youtube.com/user/CppCon or ACCU Conference: https://www.youtube.com/channel/UCJhay24LTpO1s4bIZxuIqKw where many of the discussions are about all these kind of pitfalls with just about every C++ feature and how the programmer should avoid them.

But yes, C++ can do everything Rust can, and vice versa. They are complete programming languages in that respect.

C++ does not have an equivalent of lifetimes, but lifetimes is not something that Rust does per se. Lifetimes are a guard rail that prevents you from doing incorrect things. Or in other words, C++ can do anything that you can do in Rust, but you may need to do it in a different way than in Rust, and that different way would not involve lifetimes.

4 Likes

Sorry i should have included the link that i read

I am primarily cared about whether C++ can offser the lifetime/borrow-check safety that rust does

1 Like

"C++ does very little to prevent the programmer making mistakes re: object lifetimes' --> THAT is primarily what I wanted to know. Thx. The link is provided at the end

That sort of statement if very vague. What can a programming language “do”? One could go as far as to say “Rust/C++ can meet these arbitrary requirements FOOBAR that we have for programming languages” which is the same as saying “Rust/C++ has these arbitrary properties FOOBAR”. If Rust and C++ were equally capable in this sense, for all properties FOOBAR, then C++ and Rust would have to be literally the same programming language (which they aren’t).

Leibniz’s Law

two objects 𝑥 and 𝑦 are equal if and only if 𝑥 has every property 𝑦 has, and 𝑦 has every property 𝑥 has

It's an odd thing but I don't recall "lifetime" even being in the vocabulary used by the C++ standard, any book of I have seen on C++ or discussion about it.

Until the last year or so. I started to notice a thing called "lifetime extension" being talked about in a few recent presentation. I have no idea what they were talking about, as by the time the phrase "lifetime extension" comes up they are deep into the unfathomable depths of the STL or some such.

Apparently "lifetime extension" was invented in 2015: "Accessors and views with lifetime extension" : http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0066r0.pdf

A new model associates an expression with the set of temporary objects needed to represent its value. This enables lifetime extension to work transparently through accessor functions which opt in using the export keyword. The same mechanism enables view classes and adaptors to retain an underlying container.

I'm not sure I buy that argument.

Let's consider a program as a black box, we cannot see it's internals, and only know about it's inputs and output

Then if for every possible input both programs produce the same output, they are equivalent. In all knowable ways. Any other way does not matter.

No matter what language they are written in or computer architecture they run on.

Anyway I think Alonzo Church and Allen Turing sorted out all the "equivalence" business a long time ago: Church–Turing thesis - Wikipedia

It’s more of thing of logic. I don’t see how the church turing thesis has anything to do with this. Anyways, all this could end in is a discussion what “equality” is or what “the same” means.

To apply the argument I was trying to give, just use something like “allow nonexperienced programmers to be able to easily avoid memory unsafety” for FOOBAR. Then you note that “Rust allows nonexperienced programmers to be able to easily avoid memory unsafety”.

So there you have something that Rust does, and C++ can’t do this because—as we all know—it is full of memory-safety-footguns. Clearly it is thus not true that “C++ can do everything Rust does”, assuming you count “allow nonexperienced programmers to be able to easily avoid memory unsafety” as something that a programming language „does“.

If you count “not supporting [C++-style] object-oriented class definitions” as something that a programming language does than that’s another thing that Rust does and C++ doesn’t. If you allow “being a different programming language than C++” then that’s a thing that Rust does that C++ doesn’t do. Actually that’s something that any programming language except for C++ does.

If you’re now thinking that most of the above things aren’t relevant things that programming languages do — well, that’s probably true. Rephrase the statement to “"modern C++" can do everything relevant that Rust does”. What’s relevant? Probably ultimately a matter of opinion. Being of the opinion that something is relevant is similar to caring about something. So if some person says “"modern C++" can do everything relevant that Rust does” it ends up meaning not much more than “"modern C++" can do everything that I care about that Rust does” or equivalently “I don’t care about anything that Rust does and C++ can’t do”.

6 Likes

Such a statement is too broad:

Rust program is related to four things:

  1. a language
  2. a compiler
  3. a runtime
  4. a complied program

A C++ program is also related to those four things, yet, C++ and Rust crucially differ on 1 and 2.

The C++ compiler can not and does not do the kind of static analysis a Rust compiler does. So, all those compiler supported guarantees are lost.

A clever programmer can implement in C++ rust runtime capabilities -- which, likely has already been done, since the pointer / resource handing ideas of Rust predate Rust.

Dan

I'm not suggesting you mean anything I'm about to say, but I think it is worth saying anyway:

I've seen it suggested that Rust's memory safety is good for inexperienced programmers, which it most definitely is! However in certain circles it is often suggested if you are "good enough" or a "real programmer", then you don't need Rust's safety rails. I think multiple decades of massive security vulnerabilities from even some of the world's best coders proves this false. On top of that, just watching how fraught examining a design for UB can be shows that Rust helps all programmers avoid memory unsafety, regardless of skill level.

2 Likes

Yeah, I know, and I intentionally avoided this point by including the words “inexperienced” and “easily”, since my main point was just to apply my logical argument with some property of Rust that isn’t really factually debatable, while going in the same direction as what has been said earlier in this thread.

Nevertheless I agree with everything else you say.

2 Likes

OK. I will buy that kind of argument.

It's not something that can be conclusively proved or disproved with any kind of logic. Involving the human programmer as it does. But it seems very likely to me and something that could be demonstrated statistically over time. Given enough beginner programmers and programs and fault analysis.

Scratch that: Let's formalise it...

We could imagine creating a program that endlessly generates syntactically correct C++ and Rust at random. Not with any particular meaning, as long as it's creations compile without warnings. In short, replace the human beginner with a random number generator. About the same thing, right :slight_smile:

Then we run those compiled creations and see which of them crash and burn through memory use errors.

All we need to do then is compare the results.

However, the learning curve of Rust, even for experienced programmers, is very steep.

Also, on a more theoretical note -- from what I understand the Rust paradigm for memory compiler checks is undecidable -- i.e. the rust compiler makes broader assumption that necessary to complete the task -- hence, when Rust compiler complains, the reason may not be obvious to the programmer.

This can be very confusing for novice and experienced developers alike.

See the excellent paper Will Crichton at Stanford University, where i gleaned those insights:

1 Like

How about some things that aren't safety-related? Safety is only a single facet of the language. Rust has ADTs, pattern matching and procedural macros opening the door to language extensions. Sure, you could build the semblance of these things in C++, but at that level one could also claim the same of pure C if it reaches the same result.

2 Likes

I can't count the number of times that argument has been put to me as a reason to not need something like Rust.

Every time I hear it it reminds me that I have never heard anyone who plays slot machines a lot tell me they lost. How I have never heard anyone criticise their own driving skills.... and so on. Yet slot machines make money for their owners and people die in road accidents. Something does not add up.

2 Likes