4 ms·
C++ you get templated generic algorithms that in practice no one really does with C because macros suck too much. So in C typically you'd have a runtime generi
by loeg 5mo ago
C++ you get templated generic algorithms that in practice no one really does with C because macros suck too much. So in C typically you'd have a runtime generic routine that doesn't inline. A classic example here is qsort() vs std::sort().
- afdbcreid 5mo agoI explicitly acknowledged that: > The only candidate is using virtualization and void* pointers instead of monomorphized generics which some C code does for the lack of better options, but that's not a problem in Rust as well. But in fact, if speed is a concern to you, even in C you will use "templated" sorting (via macros or code generation).
- 20k 5mo agoThe problem is that the implementation burden with C is so high, that people tend not to do it even in relatively performance constrained situations
- fluffybucktsnek 5mo agoNeither codegen nor macros (they are a part of the preprocessor) are really a part of C. For the latter, the lack of integration becomes more noticeable if you try writing a macro in which the compare param can accept a function identifier. As the preprocessor doesn't have the knowledge of the contents of the referred function, it can't inline it. In C++ and Rust, their compilers do, so they can. A codegen tool could overcome this, but you could also make a codegen tool to write Zig/D/C#/Swift in C, or any other language for that matter :). By this point, one could say you are programming in a superset of C, not strict C.
- loeg 5mo ago> in practice no one really does with C because macros [and codegen] suck too much
- flohofwoe 5mo ago> So in C typically you'd have a runtime generic routine that doesn't inline. With LTO you get many of the same advantages as C++ template code, there's nothing magic about C++ template optimizations, it's all about whether the compiler can see all function bodies in a call hierarchy.
- simonask 5mo agoLTO cannot change the layout of structs. For something like a hash map implementation, it matters whether inner nodes store a pointer to the key and value, or whether it stores a pointer to each. To achieve this in C, you have no other options than emulating templates using macros.
- flohofwoe 5mo agoThe question is whether a hash-map implementation that works on a general `[key, index]` item and where index references at separate array of values isn't actually better for some access patterns ;) And of course the other alternative to macros is code-generation (but macros are actually often fine). But this also only matters for actually reusable generic code. If I'd implement a super-hot-path hashmap in C, I would stamp out a specialized version by hand instead of relying on a generic implementation. But for 90% of cases, a solution like in stb_ds.h is probably good enough.
- simonask 5mo agoSure, but now you're actually moving the goal posts. We're talking about the practicalities - you can always achieve the same by doing more work, but it makes a difference that Rust gives you `HashMap` in the standard library that you can just use and get best-in-class performance, every time, with zero work, zero maintenance. The only choice you have to make is which hash function you want to plug into it, and since it is generic, that gets optimized and inlined as well (even with LTO disabled).
- nicoburns 5mo agoRust also has these advantages of course
- tialaramex 5mo agoIndeed Rust's standard library provides much better sorts both in terms of performance and in terms of resistance to abuse than those provided in the big three C++ implementations.
- loeg 5mo agoRight. I'm mostly addressing GP's first question about C and C++.