Hacker News new | ask | show | jobs
by tialaramex 1115 days ago
But this isn't something the C++ language provides, which is hilarious.

C++ keeps C's crap array type as its native array type. You need to reach into the C++ standard library to get this awkward library type, std::array<type,N> and then finally you get an array type that remembers how big it is and has some basic features like swap.

2 comments

True, but it also adds lot of features that help to easily migrate to saner features without rewriting the world and throw away 30 years of tooling.

Microsoft security team is on the record that just because they are adopting Rust, they won't shy away from C++.

I'm kind of on board with this, but the problem is that it's 30 years of rotten wood. Rust started from a more secure foundation and has put a lot of effort into stabilising even the trickier ground - whereas in C++ it's too often "Yeah, we don't think about it too hard, when there are strong winds I don't go up into the top floor, the creaking is very loud, I'd rather just never find out".

Example, Rust 1.0 had std::mem::uninitialized::<T>() which gives a T but it's obviously uninitialized. It's marked "unsafe" of course, but is that enough? Turns out they later realised that no, it's strictly never OK to do this, so the unsafe label was insufficiently cautious. Today std::mem::uninitialized is deprecated, Rust never removes stuff from the standard library, but you should not use this library call.

The type MaybeUninit<T> is the fix. Since MaybeUninit<T> might not be initialized, it's OK if it's not initialized, and since it might be T, it's OK for it to occupy the same amount of space as T. So, then we can initialize this memory, and tell the compiler it's initialized now, it's a T not a MaybeUninit<T>.

Can you guess how that works? It's pretty clever, and C++ could do almost the same trick, but it never has and my guess is it never will. If you don't know and are wondering, check that type definition carefully - MaybeUninit<T> is a union

For contrast, in his safety talk Bjarne Stroustrup just says as if it's obviously true, that it's safe to have uninitialized char arrays in C++. And his rationale sounds exactly like how std::mem::uninitialized happened - any possible value of a byte is a valid byte, so that's good enough, right? Nope, ask compiler engineers, there were plenty in the room when Bjarne said that, but he didn't ask them.

Sometimes it is better to have rotten wood to build something than nothing at all.

If we want to encourage Rust adoption, it is by having a middle path, not via Rust Advocacy Strike Force.

That only shuts the audience off, specially when Rust has a glass ceiling of depending on C++ infrastructure for its reference compilers.

I believe conventionally they're called the Rust Evangelism Strike Force.

And it's true that the rotten wood was better than nothing. Nobody is suggesting that NT or Linux should somehow have been developed in Rust in the 1990s. But likewise we shouldn't resist renewal in newer, better materials.

That applies to compiler internals too. Plenty of trouble down there for C++, it's just that C++ programmers can more often be sent away by assuring them that what they did was UB and so LLVM is entitled to miscompile it whereas the Rust people keep arriving with the receipts, in the form of LLVM IR that is lowered to machine code which makes no sense

e.g. https://github.com/llvm/llvm-project/issues/45725

Yet if I want to contribute to Rust backend, or its upcoming GCC implementation, write C++ I must.

Same applies to the runtimes of the languages I use at work, and GPGPU related tooling when not using shaders.

Maybe then do a Go/zig/D, focus on cranelift and fully bootstrap Rust, before trying to rewrite the world.

You certainly can go work on Cranelift or similar projects which have a coherent IR as a central goal rather than eh, it's probably good enough to compile C++.
>"std::array<type,N>"

Unless you mean array of anything like in typeless dynamic languages I do not see anything awkward about STL arrays in C++.

It's a standard library feature, rather than a language feature.

And you might say, "Who cares? Even freestanding has the standard library". Nope, std::array wasn't added to freestanding. You can dig into the messy details for yourself if you want, but suffice to say your freestanding C++ doesn't have std::array

So the C++ language has "arrays" but they're garbage, and if you point out that the arrays are garbage you're told to use this library feature, which may not be available.

The only valid complaint about std::array is that it's awkward to declare and takes more characters to type. It is, otherwise, vastly superior in every other way.

That doesn't make them garbage. That makes them annoying.

I feel like I already explained it's not even part of the language itself, it's a library feature, you aren't given this feature without the rest of the hosted C++ standard library.

Which is fine if you write Windows desktop apps, but this is an array type, unlike a GUI widget, or an XML parser, it seems like I'd probably want an array type for this $1 per unit micro controller I'm writing firmware for. In Rust the nice array type works just fine, it's a proper first class type, it knows how big it is, mutable arrays coerce into a slice I can sort (only unstably, but hey, we're embedded firmware let's not get fancy), I can iterate over it properly... in C++ only the crappy C-style array is available unless I can butcher the std::array so that it works outside the hosted library. Ugh.

You do not have to butcher. Standalone allocation free implementations are available if you are so in need.

But I see that you bring Rust in here. If that's your cup of tea then use it. No need to spill venom. Personally if I am dealing with $1 micros I very much prefer C with some selected libs for embedded. Do not really have problems with it for such small tasks.

>"takes more characters to type."

I have never perceived it as a problem. I do not think it really slows my programming. Personally I am the guy who would prefer function() vs fn() but without going into extremes of Java culture. Besides you can always alias it to whatever you want if your fingers are so sensitive.

>"feature, which may not be available"

Never been into this situation so from a practical standpoint it means zilch to me.