Skip to content(if available)orjump to list(if available)

How to write type-safe generics in C

How to write type-safe generics in C

29 comments

·November 15, 2025

schaefer

A more accurate title would be:

“How to write type safe generics using the C preprocessor”

lelanthran

Having used this in production around 2004, I never really liked this approach - abusing the preprocessor this much shouldn't be necessary and the result is almost unreadable.

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.

david2ndaccount

I wrote a similar article in the past: https://www.davidpriver.com/ctemplates.html

I use this technique in my hobby projects as it has worked out the best for me of the options I’ve explored.

jesse__

I wrote a metaprogramming language that adds another option to the list, for anyone that's interested : https://github.com/scallyw4g/poof

variadix

You can create macro functions per generic function so something like Vector_New(int)(&v) expands to Vector_New_int(&v). It also looks less foreign (more like templates) than the G macro.

pjmlp

Type safety, generics and C is a bit of oxymoron.

synergy20

or use nim metaprogramming, which will be transpiled to c

null

[deleted]

self_awareness

Well, another option would be to use a C++ compiler, which supports templates, but limit the use of classes through a coding convention standard.

krupan

Not sure why this is down voted when the whole point of TFA is to torture the C language into doing something it can't really do. I guess there's an unspoken assumption in TFA that you are stuck using C and absolutely cannot use a different language, not even C++?

relling

[dead]

flashgordon

Actually this was my first instinct too. Just limit what you use c++ for and write c code with templates and be done with it.

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

What would be the detrimental effect of using smart pointers?

lelanthran

> Well, another option would be to use a C++ compiler, which supports templates, but limit the use of classes through a coding convention standard.

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

"ask the developers to practice discipline" is a baseline requirement for coding in C

lelanthran

> "ask the developers to practice discipline" is a baseline requirement for coding in C

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.

pjmlp

Unfortunately the majority has failed to attend the temple classes on such practices.

Loudergood

If only.

hawk_

Is there a way to pass compiler switches to disable specific C++ features? Or other static analysis tools that break the build upon using prohibited features?

fweimer

No two development groups agree on the desired features, so it would have to be a custom compiler plugin.

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.

pjmlp

C folks rather reproduce badly C++ than acknowledge its Typescript like improvements over C.

pron

C is sometimes used where C++ can't be. Exotic microcontrollers and other niche computing elements sometimes only have a C compiler. Richer, more expressive languages may also have additional disadvantages, and people using simpler, less expressive languages may want to enjoy some useful features that exist in richer languages without taking on all of their disadvantages, too. Point being, while C++ certainly has some clear benefits over C, it doesn't universally dominate it.

TS, on the other hand, is usable wherever JS is, and its disadvantages are much less pronounced.

pjmlp

It isn't the 1980's any longer, there isn't a chip in such scenarios other than PIC class, even AVR get to use C++.

lelanthran

> C folks rather reproduce badly C++ than acknowledge its Typescript like improvements over C

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

Nah, it is called life experience meeting those kind of persons since the 1990's, starting on BBS forums.

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.