Earlier quoted context omitted.
I agree that you shouldn't be doing this stuff in production if you don't know the ends and outs of doing this idiomatically. For instance, the lack of parenthesis ala #define SQ(x) ((x)*(x)) set off my C spidey senses. I use them even for constants in pound defines just to be consistent. That being said, there are benefits, like the type safety listed being one of them. No weird cast to void* and go to town on raw m…
You mean: #define SQ(x) ((x)*(x))
Type-safe generic data structures in C
21–30 of 57 posts
Re: Type-safe generic data structures in C
#22Why would anyone use this when there is C++, Rust, etc? Genuinely curious.
Re: Type-safe generic data structures in C
#23A better pattern instead of declaring via a macro that expands to a large number of functions is to define the implementation in a file, require the user to #define STACK_T and then #include the file. At the bottom of the file, #undef STACK_T. As files can be included multiple times, you can do this for each generic structure you like. A sort of poor-man’s templates, that you can reasonably step through in a debugger…
Note that include guards become tricky then.
Re: Type-safe generic data structures in C
#24Why would anyone use this when there is C++, Rust, etc? Genuinely curious.
Even calling C++ code from compilers other than the one you were using (e.g. you are using a 3rd party precompiled library) is a risky proposition.
Re: Type-safe generic data structures in C
#25Why would anyone use this when there is C++, Rust, etc? Genuinely curious.
The downside of course is that generics and iterators on those are a bit more troublesome, only compiler dependent goodies (mostly only clang, not gcc), like overloads or constexpr. C++ templates are ugly, and the STL is very buggy and limited. Also no security and no performance. They started on the wrong foot and had to keep it there.
Rust has an annoying syntax, but a much better library culture.
Re: Type-safe generic data structures in C
#26Re: Type-safe generic data structures in C
#27Author here. I wish I had made it clearer that the intent of the post was "this is an interesting and surprising thing you can achieve in C" and not "this is a good idea for a real software project" or "this is a reason to use C instead of C++/Rust/Go".
Re: Type-safe generic data structures in C
#28Why would anyone use this when there is C++, Rust, etc? Genuinely curious.
C is still, I have to imagine, the closest thing we have to a language available for all platforms that exist today, while C++ is heavily burdened with featuritis and Rust is limited in platform support.
Rust supports everything you are likely to see in the wild outside of highly, highly specialized applications (e.g. ancient mainframes, satellites from the 80s or 90s, etc.).
For God's sake, it's becoming increasingly difficult to justify writing code that takes into account CPU endianness, because all CPUs that are likely to run your code are little endian!
Re: Type-safe generic data structures in C
#29A better pattern instead of declaring via a macro that expands to a large number of functions is to define the implementation in a file, require the user to #define STACK_T and then #include the file. At the bottom of the file, #undef STACK_T. As files can be included multiple times, you can do this for each generic structure you like. A sort of poor-man’s templates, that you can reasonably step through in a debugger…
I've open sourced my own C template library here:
https://github.com/ludocode/pottery
Not only does it use the #include style of templates, but it actually makes the templates composable. It takes this idea pretty far, for example having a lifecycle template that lets you define operations on your type like move, copy, destroy, etc. This way the containers can fully manage the lifecycles of your types even if they're not bitwise movable.
There's also this other more popular C template library, one that tries to more directly port C++ templates to C but with a lot less features:
Re: Type-safe generic data structures in C
#30Earlier quoted context omitted.
I've started moving to using python to generate what I need a lot of the time now in C. I'll either make a '.h' file, read it in and generate the boilerplate I need, or just do it using native python and emitting the C I need. I'm never again hand-writing an my_enum_to_str routine.
I share your feelings, though some years ago I discovered the neat trick of "xmacros". In a nutshell: #define COLOR_LIST \ X( RED ) \ X( GREEN ) \ X( BLUE ) \ X( PURPLE ) enum Color { #define X(code) code, COLOR_LIST #undef X }; static const char* colorNames[] = { #define X(code) #code, COLOR_LIST #undef X }; You can even make it cleaner and store more metadata: // --- color.def X( RED, "Red", 0xFF0000 ) X( GREEN, "G…
#undef X
when you're done.