Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Isn't this a use-case for _Generic[1]?

[1]: https://en.cppreference.com/w/c/language/generic



_Generic is a little bit broken[1].

It's a lot like some of the other decisions by the standards committee; they see demand for a particular feature $FOO, then add in support for something not quite like $FOO, which maybe addresses part of what was wanted but turns out useless in practice so that few use it.

They added `const` (which, admittedly, does get a lot of use in practice) which is subtly different from what already existed in C++ at the time.

They added VLAs, then had to walk that back because, like `gets()`, there was no practical way to use it safely.

The added _Generic, which requires the typenames to be known in advance.

They added threads, but without wide enough functionality to use it for anything but the most trivial of programs.

All in all, they've been doing a poor job of steering the language in the last 20-odd years since C99. What users have been clamouring for was "less UB, please? Make it IB where you can", but instead they have been adding UB.

In the words of Linus Torvalds: "Yeah, let's just say that the original C designers were better at their job than a gaggle of standards people who were making bad crap up to make some Fortran-style programs go faster."

Original K&R C had no reference to undefined behaviour. The worst you could say about C at that point in time was that some things were defined by the implementation.

[1] Some might say more than a little bit :-/ You can't use it to write type-safe generic libraries.


> Original K&R C had no reference to undefined behaviour.

You don't have to explicitly refer to undefined behavior to have it. If you just merely omit defining the behavior of certain programs then that's enough.


> You don't have to explicitly refer to undefined behavior to have it. If you just merely omit defining the behavior of certain programs then that's enough.

I respectfully disagree. It can be implementation defined, as in all other languages.

In fact, when I started with C, I did not use a C89 one, if we weren't certain what a certain construct did, we;d try it on a compiler and use the result as a definition for what that construct did on that compiler!

On another compiler it might do something else, but that didn't bother us until it was time to port the code to another compiler.

With undefined behaviour being added, that no longer holds: you try something out, get a particular result, but the next time you compile that construct you could get a completely different result.


> In fact, when I started with C, I did not use a C89 one, if we weren't certain what a certain construct did, we'd try it on a compiler and use the result as a definition for what that construct did on that compiler!

This still doesn't mean that the behavior was implementation defined. Implementation defined requires the compiler vendor to document the behavior. However implementers are allowed to define and even document the behavior for operations that the standard leaves undefined. These are called extensions. It's common practice to have some extensions even now, sometimes behind specific compiler flags, or just being documented.

I think it's a mistake to infer the compiler's behavior through trying a few examples, even for simple compilers. If you want to have guarantees for the behavior for otherwise undefined constructs then get it in writing from the compiler vendors. Even if you check the source code, the behavior might change in a future version.


With _Generic, the original library implementor has to accommodate your type. If it's a “template”, the user can insert their type. Also a type that's created long after the original library author has finished their work.


It's also the case that _Generic is only available in C11 while this library targets C99




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: