
Generics in C without void* or macros – enabled by psychec - unusualcool
https://github.com/ltcmelo/psychec#generic-programming
======
blazemaster
I don't really understand what the point of all this is, and why anyone would
consider using this in a real-world application they're developing. There's
already a C-like language which lets you write type-safe generic programs:
it's called C++! And if for some reason you really want or need to restrict
yourself to using C language features (almost) exclusively, you can disable
RTTI, exceptions, and use a technique to avoid linking to libstdc++ (or
equivalent). It really seems to me that the point of all this is just to
reinvent the wheel, but maybe I'm missing something, I only skimmed the paper.

~~~
Crinus
The problem with C++ is that in addition to generic functionality, it also
brings a ton of other baggage that even if you do not use, you still pay for
(e.g. personally i really dislike how slow C++ compilers are).

Though TBH i wouldn't use OP's preprocessor either as i think that void* and
macros are perfectly fine.

~~~
wvenable
One of the reasons C++ is so complicated is that you don't pay for the
features that you don't use. If you wanted generics in C, you can easily use
C++ without any of those other features (baggage, if you will) and not pay for
it.

Heck, you could define a few macros and make it impossible to use any baggage
features you don't like.

I've used C++ in a pretty tight embedded environment and it was great.

~~~
bsder
> I've used C++ in a pretty tight embedded environment and it was great.

I'd love to hear some details. I'm always looking for C++ stories that didn't
end in disaster and what the people did that worked.

~~~
com2kid
I've done similar. The Microsoft Band UI was written in C++. No templates or
other advanced features, compiler was stuck on 2003 standard. We had templates
but used the trick of implementing them in a .cpp file and declaring all the
instanciations of them we'd ever use at the bottom of the same file. Had to
write our own to guarantee 0 allocs.

It is quite do-able. Lots of static declarations, basically write C with
classes. V-tables ended up being non-trivial in size, but what can you do,
GUIs and all that. Possibly the best (only?) good use of inheritance
hierarchies.

256KB memory, the UI only had 60KB or so available for it IIRC. We also had a
scratch pad available over a super slow bus of a couple megs, but it couldn't
be used too much or we'd drop frames and we loved our 30fps v-sync'd
performance.

------
TorKlingberg
No void* or macros, but requires a special compiler frontend.

~~~
jackewiehose
Yes, that was confusing. "Look, you don't need to use these C-features if you
use another language than C."

~~~
klingonopera
C++ 14, Haskell _and_ Python.

One of the reasons I'm actually going for pure C in this modern day and age,
is that I can just write a small program, without having any other dependency.

I'm sure the same could be said for C++, too, but for some reason, with my
setup (GCC 5.1.0 with MinGW on Windows 7), I'm averaging around 800KB on C++
vs 80KB on C, for the (mostly) same code. _EDIT:_ It appears that exception-
handling is one of the reasons the binary is bigger in C++ than C.

I mainly write code for embedded devices, so whatever programs I write on x86
is to interface with those devices, hence I'm quite comfortable staying with
C.

~~~
Crinus
Are you sure it isn't debugging information that bloats the executable? Try a
strip --strip-all your.exe and see if it is still that big.

~~~
klingonopera
> _Try a strip and see if it is still that big._

...I guarantee that it is nothing short of _humongous_ xD

Joking aside, maybe, I don't know, it's been a while since I used some C++
code, but I'll have a look into it the next time around.

...though it's probably unlikely, I use Code::Blocks and exclusively use the
"Release" candidate, and uncheck the "Debug" version, and I'm quite confident
the CB authors know what they are doing.

~~~
Crinus
I do not remember Code::Blocks' configurations, but a Release configuration
may still contain debug symbols so you can debug your release executable.

------
nitrix
You should never typedef a pointer to an object. That’s common knowledge
amongst experienced C developers and an immediate red flag, even for myself
normally welcoming of anything built with Haskell.

~~~
bitcharmer
I'm not an expert C developer but can see some semantic benefits of typedefing
a pointer.

Is this considered harmful because it hides the fact that you're dealing with
a pointer in the first place?

~~~
raxxorrax
As evidenced by countless examples of somethingPTR-types, it is done
regularly. But the main problem is indeed that you hide the pointer.

If you apply qualifiers like const to your type, results might me unexpected.

It might have semantic benefits, but C developers should be trained to ignore
all these strange *-symbols anyway.

------
bitwize
So to program C in this special way I need C++, Haskell, _and_ Python. No
thank you. If/when I still work in C, it's with the aim of keeping bloat and
dependencies to a dull roar at most.

------
zenogais
Type generic expressions [1] already exist in C11. You can do this without a
special compiler front-end if you need it, you would just need to define each
variant by hand. These are supported in GCC and Clang with the -std=c11 flag.

[1]: [http://www.robertgamble.net/2012/01/c11-generic-
selections.h...](http://www.robertgamble.net/2012/01/c11-generic-
selections.html)

~~~
AndrewBissell
I developed these ideas a bit further with the use of XX macros, which allow
you to make a set of functions generic across some list of types. There can be
real performance wins to this over void*:
[https://abissell.com/2014/01/16/c11s-_generic-keyword-
macro-...](https://abissell.com/2014/01/16/c11s-_generic-keyword-macro-
applications-and-performance-impacts/)

~~~
flukus
That looks handy. I got bored one day and built a fluent interface:
[http://flukus.github.io/fluent-interfaces-
for-c.html](http://flukus.github.io/fluent-interfaces-for-c.html)

------
kbbr
I like C for the small set of basic rules and that it does not impose much
cognitive overhead of learning too many new things for a given project I have
to get to know. Typedefs were already too much and I prefer not to use them...

~~~
Koshkin
Typedefs are nice if you do not want to write 'struct' all the time...

~~~
klingonopera
Yes! Typedefs are definitely worth the time spent learning them.

------
kristoff_it
Interesting link, but if anybody is interested in making real practical use of
generics in a C-style language, then it's best to take a look at Zig.

~~~
potiuper
Zig is not able to output c code that could be consumed by an alternative
[optimized|verified/proofed] C compiler like Intel along with other
questionable decisions such as "Zig does not support RAII or operator
overloading because both make it very difficult to tell where function calls
happen just by looking at a function body. Zig tends to avoid syntactic sugar
except where it would have a significant effect on the semantics of a program.
Zig does not have a C-style for loop, because you can just use the more
general-purpose while loop instead with only a little bit of extra code. [1]
The compiler is free to inline non-extern functions, change their parameters,
and otherwise !!do whatever it wants!!, since they are internal functions."
[2]

[1] [https://ziglang.org/download/0.1.1/release-
notes.html](https://ziglang.org/download/0.1.1/release-notes.html) [2]
[https://andrewkelley.me/post/intro-to-
zig.html](https://andrewkelley.me/post/intro-to-zig.html)

~~~
AndyKelley
Just a note for drive by viewers, there's a link here to 0.1.1 release notes
but a lot has changed since 0.1.1:

* [0.2.0 release notes]([https://ziglang.org/download/0.2.0/release-notes.html](https://ziglang.org/download/0.2.0/release-notes.html))

* [0.3.0 release notes]([https://ziglang.org/download/0.3.0/release-notes.html](https://ziglang.org/download/0.3.0/release-notes.html))

* [0.4.0 release notes]([https://ziglang.org/download/0.4.0/release-notes.html](https://ziglang.org/download/0.4.0/release-notes.html))

0.5.0 is scheduled to be released Sept 30.

------
jasonhansel
Can you add existentially-quantified generics? Then OOP with dynamic dispatch
would just be syntactic sugar. IMHO this would be way better than C++ since it
would completely unify generics with the OO approach.

