“How to write type safe generics using the C preprocessor”
I think a better way is possible using `_Generic`[1]. Even though it would still use macros, the resulting code is much more readable.
---------------------------
[1] `_Generic` comes with its own problems too, of course.
The readability of error messages was always my beef with macro-based generics. Maybe 15 years ago I played around with using UTF characters for the brackets and type separators when translating a generic type into name-mangled type, so at least the generated source and error messages would still be clear and understandable.
Robust UTF support for identifiers and preprocessor was still kind of inconsistent across compilers though, so it only sort of worked. I expect this has improved considerably now though, so maybe I should try again and write something up. You can embed a surprising amount of advanced programming language theory into suitable name resolution.
I use this technique in my hobby projects as it has worked out the best for me of the options I’ve explored.
This is secretly two way generation: you can edit The generated file, recompiling until until the code works, commit that, and then edit the M4 inputs until CI passes.
As another example of the same principle, whenever I am required to have a requirements.txt and setup.cfg in the same puthon library, I now verify that they match in a CI check instead of trying to single source of truth by having a setup.cfg import the requirements.txt through some clever hack.
This is how you do it:
Although it's a toy not for production, it's very interesting that the idea of traits/concept/typeclass just "emerge" out of the code, which made me suddenly understand why STL come into being.
(you could also create a version with capacity, of course, but I like it this way).
self_awareness•2mo ago
lelanthran•2mo ago
When the other option is "ask the developers to practice discipline", an option that doesn't require that looks awfully attractive.
That being said, I'm not a fan of the described method either. Maybe the article could have shown a few more uses of this from the caller perspective.
krupan•2mo ago
pjmlp•2mo ago
lelanthran•2mo ago
Sure, but since there's 10x more opaque footguns in C+++, there is much less discipline needed than when coding in C++.
The footguns in C are basically signed-integer over/underflows and memory errors. The footguns in C++ include all the footguns in C, and then add a ton more around object construction type, object destruction types, unexpected sharing of values due to silent and unexpected assignments, etc.
Just the bit on file-scope/global-scope initialisation alone can bite even experienced developers who are adding a new nonlocally-scoped instance of a new class.
Loudergood•2mo ago
EPWN3D•2mo ago
The solution to this doesn't have to be "rewrite everything in Rust", but it does mean that you need to provide safe, easy implementations for commonly-screwed-up patterns. Then you're not asking people to be perfect C programmers; you're just asking them to use tools that are easier than doing the wrong thing.
krupan•2mo ago
relling•2mo ago
pjmlp•2mo ago
lelanthran•2mo ago
This is a rather crude misrepresentation; most C programmers who need a higher level of abstraction than C reach for Java, C# or Go over C++.
IOW, acknowledging that C++ has improvements over C still does not make the extra C++ footguns worth switching over.
When you gloss over the additional footguns, it looks like you're taking it personally when C programmers don't want to deal with those additional footguns.
After all, we don't choose languages based on which one offers the most freedom to blow your leg off, we tend to choose languages based on which ones have the most restrictions against blowing your leg off.
If your only criteria is "Where can I get the most features", then sure, C++ looks good. If your criteria is "Where are the fewest footguns", then C++ is at the bottom of the list.
pjmlp•2mo ago
My criteria is being as safe as Modula-2 and Object Pascal, as bare minimum.
C++ offers the tools, whereas WG14 has made it clear they don't even bother, including turning down Dennis Ritchie proposal for fat pointers.
lelanthran•2mo ago
> it is called life experience meeting those kind of persons
Looks like you are confirming that you are taking it personally.
I don't understand why, though.
You cannot imagine a programmer that wants fewer footguns?
pjmlp•2mo ago
lelanthran•2mo ago
Well, that's a novel take: "Opting for fewer footguns is careless". :-)
It's probably not news to you that your view is, to put it kindly, very rare.
pjmlp•2mo ago
And to finish this, as I won't reply any further,
"A consequence of this principle is that every occurrence of every subscript of every subscripted variable was on every occasion checked at run time against both the upper and the lower declared bounds of the array. Many years later we asked our customers whether they wished us to provide an option to switch off these checks in the interests of efficiency on production runs. Unanimously, they urged us not to--they already knew how frequently subscript errors occur on production runs where failure to detect them could be disastrous. I note with fear and horror that even in 1980 language designers and users have not learned this lesson. In any respectable branch of engineering, failure to observe such elementary precautions would have long been against the law."
-- C.A.R Hoare's "The 1980 ACM Turing Award Lecture"
lelanthran•2mo ago
Like this quote here that you posted.
pjmlp•2mo ago
First of all the quote there is indirectly about C with UNIX's adoption starting out of Bell Labs, C++ would only become known to the world in 1989, with the release of CFront 2.0.
Second, while you certainly can code C in C++, just like one can code JavaScript in TypeScript, the tools are there on the type system for anyone that cares, tools that WG 14 has proven not to care in 50 years of history.
Third, all C compilers worth using in professional scenarios are nowadays written in C++.
As last point, while C++ has the heads up over C in type system improvements, it is by no means the final answer in systems programming, ideally both programming languages should be replaced by better, safer ones, which there are a few already to chose from.
Unfortunely as long as LLVM and GCC are around, industry standards based on C and C++, there is little hope that those improved languages fully take over.
Thus when it comes to C vs C++, in such world where else gets to replace them in all scenarios, C++ is the only answer to that duality of choice, unless one wants to keep re-inventing solutions (badly) for answers C++ is providing since 1989.
lelanthran•2mo ago
The only question was whether you're doing it on purpose or whether you really do think that there are zero programmers who want fewer footguns.
As far as the C vs C++ thing goes, if your measure is "How many OPTIONAL features does a language give me WRT safety", then sure, C++ is optionally safer than C.
If the measure is "How many extra footguns does the language provide", then no, C++ cannot, by any objective measure, be safer than C.
Since you're constantly re-framing the discussion towards "More features" and away from "fewer footguns", I think it is safe to say that "extra footguns", for you anyway, doesn't mean "less safe".
The way you constantly re-frame, though, reflects quite poorly on you - it's pretty obvious from the very first thread I am counting the footguns as the measure of how unsafe a language is. That's not an irrational measure, and yet you are willing to strawman the argument to make it seem irrational.
pron•2mo ago
TS, on the other hand, is usable wherever JS is, and its disadvantages are much less pronounced.
pjmlp•2mo ago
pron•2mo ago
C++ has many advantages over C, but it also brings some clear disadvantages that matter more when you want to be aware of every operation. When comparing language A against language B, it's not enough to consider what A does better than B; you also have to consider what it does worse.
That's why I don't think that the comparison to TS/JS is apt. Some may argue that C++ has even more advantages over C than TS has over JS, but I think it's fairly obvious that its disadvantages compared C are also bigger. For all its advantages, there are some important things that C++ does worse than C. But aside from adding a build step (which is often needed, anyway), it's hard to think of important things that TS does worse than JS.
pjmlp•2mo ago
If there is any C, it is hardly any different from using C as cheap macro Assembler, with lots of inline Assembly.
Also definitely a 1980's CPU.
It is more than apt, until C gets serious about having something comparable to std::array, span, string_view, non null pointers, RAII, type safe generics, strong typed enumerations, safer casts,...
Among many other improvements, that WG14 will never add to C.
pron•2mo ago
Alongside all of its useful features, C++ brings a lot of implicitness - in overloading (especially of operators), implicit conversion operators, destructors, virtual dispatch - that can be problematic in low-level code (and especially in restricted environments). Yes, you can have an approved subset of C++, and many teams do that (my own included), but that also isn't free of pitfalls.
pjmlp•2mo ago
There is an endless list of edemic C pitfalls that WG14 has proven not to care to fix.
Auto industy has come up with MISRA, initially for C, exactly because of those issues.
Ideally both languages would be replaced by something better, until it doesn't happen, I stand by my point, the only reason to use C instead of C++, it not having a C++ compiler available, or being prevented to use one, like in most UNIX kernels.
I hold this point of view since 1993, having used C instead of C++ was only when obliged to deliver my work in C, due to delivery requirements where my opinion wasn't worth anything to the decision makers.
So if I was already using C++ within the constraints of a 386 SX, running at 20 Mhz limited to 640 KB ( up to 1 MB) RAM size, under MS-DOS, I certainly will not change it for the 2025 computing world reality.
pron•2mo ago
1718627440•2mo ago
Tell me how to use C++, without using RAII. You can't. Not being able to automatically allocate without also invoking the constructor is what I dislike the most in C++. Other things are, that you can never be sure, what a function call really does, because dynamic dispatch or output parameters aren't required to be explicit.
> I hold this point of view since 1993, having used C instead of C++ was only when obliged to deliver my work in C, due to delivery requirements where my opinion wasn't worth anything to the decision makers.
https://floooh.github.io/2019/09/27/modern-c-for-cpp-peeps.h...
C isn't ANSI C anymore!
flashgordon•2mo ago
The problems I am guessing start when you are tempted into using the rest of the features one by one. You have generics. Well next let's get inheritance in. Now a bit of operator overloading. Then dealing with all kinds of smart pointers...
eptcyka•2mo ago
flashgordon•2mo ago
If you can say I will only use features A, X an Z of C++ and some how enforce it then you are mitigating a lot of the risk. IIRC Carbon (Google's new lang to migrate their code off C++) came about because they themselves used C++ in a very bounded way (I recall a lot of the templates they created for their use of C++ actually resembled how Go code looked like and may have been one of the reasons for creating Go). But I am not sure how many mere mortals have that kind of tooling and discipline to limit themselves?
1718627440•2mo ago
hawk_•2mo ago
fweimer•2mo ago
You could start with a Perl script that looks at the output of “clang++ -Xclang -ast-dump” and verifies that only permitted AST nodes are present in files that are part of the project sources.
hawk_•2mo ago
pjmlp•2mo ago
As usual with additional tooling, there must exist some willingness to adopt them.
1718627440•2mo ago
EPWN3D•2mo ago