Remix.run Logo
benreesman 10 hours ago

Systems programming in the large is hard, owning the category for decades harder still.

Even languages that have tried to fast-follow and disrupt C++ end up looking a lot like C++. There is an irreducible complexity.

zbentley 9 hours ago | parent | next [-]

I hear this a lot, but I don’t really understand how this manifests in language complexity like the stuff in TFA in practice.

Like, I can understand how systems programming requiring programmers to think about questions like “how can I proceed if allocation fails? How does this code work in an embedded context with no heap?” is hard and irreducible.

But I can’t understand why a language’s choice to impose complex rules like C++ move constructor hell is an inevitable outcome of irreducible complexity in systems programming. Put another way: C is also a systems programming language that works for many people, and it doesn’t have any of these Byzantine rules (unless you build them yourself). That’s not to say C is better/preferable, but it swims in the same “official Big Gun systems language” pond as C++, which seems to indicate that revalue semantics as complex as C++’s are a choice, not an inevitability.

HarHarVeryFunny 8 hours ago | parent | next [-]

I wouldn't say issues like this are dues to irreducible complexity, but more symptomatic of long-lived languages that continually get extended but don't give up on backwards compatibility. It's basically the 2nd law of thermodynamics applied to programming languages that they will eventually die due to increased entropy.

Maybe if move semantics, and noexcept, had been designed into C++ from the beginning then the designers might have chosen to insist that move constructors be noexcept, but since these were added later there is code out there with move constructors that do throw exceptions...

Note by the way that the issue being described isn't strictly about std::move or move semantics in general, but more about the STL and containers like std::vector that have chosen to define behavior that makes noexcept move constructors necessary to be used when reallocating.

kanbankaren 5 hours ago | parent | prev | next [-]

> But I can’t understand why a language’s choice to impose complex rules like C++ move constructor hell is an inevitable outcome of irreducible complexity in systems programming.

Programmer here for 30 years in C/C++. It is true that C++ has become a more complex language after rvalue references were introduced, but you have to understand the rationale behind C++: a language suitable for large scale systems programming with *ZERO OVERHEAD*.

The language complexity especially rvalue references was to reduce overhead. Pre-C++-11, there were many code patterns that involved constructing temporaries and destroying them immediately.

C is not suitable as a large scale programming language. Just look at the number of defects in the Linux kernel and their attempt at extending the language through custom compiler attributes to overcome the limitations of C.

LexiMax 2 hours ago | parent [-]

> but you have to understand the rationale behind C++: a language suitable for large scale systems programming with ZERO OVERHEAD.

Is this the reason why C++ was created, or the last remaining niche that C++ is holding onto?

I remember the early 90's, and it very much seemed like C++ was being pushed as both a general-purpose language and the logical successor to C, insert Linus Torvalds rant here. On top of that, C++ made the decision to privilege a form of polymorphism that had pointer-chasing baked into its internal design, as well as having a good chunk of the standard library being considered a footgun best to avoid due to how much it blew up compile-times.

I think that C++ is a zero-overhead language now because a series of general purpose languages that came afterwards took the other niches away from it, plus the benefit of 30+ years worth of compiler optimizations that were originally largely aimed at the mountain of C code that was out there.

EDIT: Almost forgot about exceptions, the other enormous performance footgun that was an early pre-standard C++ feature.

usefulcat 2 hours ago | parent | prev | next [-]

> I can’t understand why a language’s choice to impose complex rules like C++ move constructor hell is an inevitable outcome of irreducible complexity in systems programming

It's not about irreducible complexity in systems programming, it's about irreducible complexity in the creation of higher level abstractions.

You could certainly implement something functionally equivalent to std::vector<std::string> in C. What you couldn't do in C is implement std::vector<T> correctly and efficiently for any type T. That's where much of the complexity comes from.

The hard part is giving the compiler enough information so that it can automate a lot of what would have to be manually written in a language like C, and to produce a result that is both correct and efficient.

cjfd 9 hours ago | parent | prev | next [-]

The difference is that in C one is supposed to do allocations and deallocations oneself. Then move semantics is just pointer assignment with, of course, the catch that one should make sure one does not do a double-free because ownership is implicit. In C++ ownership is indicated by types so one has to write more stuff to indicate the ownership.

SJC_Hacker 7 hours ago | parent [-]

> The difference is that in C one is supposed to do allocations and deallocations oneself

No, you should only use the heap if necessary.

The bigger issue in C is there is no concept of references, so if you want to modify memory, the only recourse is return-by-value or a pointer. Usually you see the latter, before return value optimization it was considered a waste of cycles to copy structs.

In the embedded world, its often the case you won't see a single malloc/free anywhere. Because sizes of inputs were often fixed and known at compile time for a particular configuration.

jesse__ 4 hours ago | parent | prev [-]

As you pointed out, the idea that a systems language requires some high level of complexity is just straight-up wrong, and demonstrably so (see, C).

The best programmers I know of have basically all abandoned C++ in favor of either languages they made, or just use plain C

drob518 9 hours ago | parent | prev | next [-]

I have no problem with systems programming issues. That complexity is essential complexity inherent in the problem itself, regardless of language. I have a problem with C++’s accidental complexity. I find C much more tractable. It certainly has a few of its own footguns, but it has much less accidental complexity.

SJC_Hacker 6 hours ago | parent [-]

As the author of the FQA noted (Yosef K-something), in C++ its more the combinations of features which causes so many issues.

And here we see this principle rear its ugly head yet again. In this case, its the combination of exceptions, manual memory allocation and the desire to make things work efficiently - of which the move constructor was developed as a "solution"

CyberDildonics 6 hours ago | parent | prev [-]

What does in the large mean?