Hacker News new | ask | show | jobs
by 2OEH8eoCRo0 301 days ago
Yup. I've often wonder why the aversion to C++ since they are obviously using objects. Is it that they don't want to also enable all the C++ language junk like templates or OO junk like inheritance?
2 comments

Here's one example. For us, it's more a tradeoff rather than an aversion. There's pros (manual memory management in C) and cons (manual memory management in C) for each. We do math operations (dense and sparse matrix math for setting up and solving massive systems of differential equations) on massive graphs with up to billions of nodes and edges. We use C in parts of the engine because we need to manage memory at a very fine level to meet performance demands on our tool. Other parts of the tool use C++ because they decided the tradeoff benefited in the other direction, re memory access / management / ease of use. As a result we need really robust qa around memory leaks etc. and tbh we rely on one generational talent of an engineer to keep things from falling apart; but we get that speed. As a side note, we implement objects in C a little more complex than the op, so that the object really does end up as a black box to the user (other engineers), with all the beauty of data agnosticism.
What parts of it can't just be compiled as C++ code? (unless it has to do with the subtle difference in implicit lifetime object rules)

IMO it's much easier to write resleaks/double-frees with refcounted objects in C than it is in C++

VLAs, named structure assignment, sane treatment of the void type, having different "lifetimes" for object (the C understanding of object) existence and initialization, having different namespaces for composed types and variables, a local error handling convention, leading to better error messages, robuster behaviour and a feeling for completeness, a lot of examples of the article and here in the thread, and most importantly no magic.
> named structure assignment

Is a thing since C++20

> sane treatment of the void type

If you're talking about conversion rules, explicit cast from void* to T* makes more sense than implicit since it is a downcast.

> VLAs

IMO these are a mistake (and C++ templates remove a lot of the need for it). They give a false sense of security and invite stack boundary overrun as many people forget to check bounds on these. I found and reported an unauthenticated RCE DoS (crash) in a distributed DB due to VLAs; worse, one cannot always assume the minimum stack size on a system.

> a local error handling convention

Exceptions are problematic in their implementation and how they are (mis)used, but they are supposed to be orthogonal to normal control flow handling, and are not supposed to replace it. They are more-or-less recoverable panics

> If you're talking about conversion rules, explicit cast from void* to T* makes more sense than implicit since it is a downcast.

Yes, but you also need to specify the type in C. ((void *)p)->foo only works in New B not in C.

> IMO these are a mistake

Forgetting to check bounds does always result in these problems in C, this is not specific to VLAs. I find them useful.

> Exceptions are problematic in their implementation

Ok, but that means to me having these in the language is only a downside.

C makes it obvious were you use that dynamism and where you don't. Syntactic sugar doesn't really make that much of a difference and also restricts more creative uses.

The C syntax is not really that complicated. Dynamic dispatch and virtual methods was already in the article. Here is inheritance:

    struct Subclass {
        struct Baseclass base;
    };
That's not really that complicated. Sure, you need to encapsulate every method of the parent class, if you want to expose it. But you are also recommended to do that in other languages, and if you subclass you probably want to slightly modify behaviour anyway.

As for stuff like templates: C doesn't thinks everything needs to be in the compiler. For example shadowing and hiding symbols can be done by the linker, since this is the component that handles symbol resolution across different units anyway. When you want templates, either you actually want a cheap way of runtime dynamism, then do that, or you want source code generation. Why does the compiler need to do that? For the basics there is a separate tool in the language: the Preprocessor, if you want more, you are free to choose your tool. If you want a macro language, there is e.g. M4. If you want another generator just use it. If you feel no tool really cuts it, why don't you write your code generator in C?