Re:Type-safe generic data structures in C
by monocasa on Thursday April 08, 2021 @11:48PM
(#26746470)
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 memory shenanigans you would have to do to use functions in intrusive collections in C.
You mean:
#define SQ(x) ((x)*(x))
Re:Type-safe generic data structures in C
by throwaway3neu94 on Saturday April 10, 2021 @02:24PM
(#26763712)
There's another pitfall: it evaluates a parameter twice. Imagine calling SQ(func_with_side_effects()).
If you can assume a compiler with statement expressions and typeof (gcc, clang, probably icc in this case):
#define SQ(x) ({ typeof(x) x_ = (x); x_ * x_ })
If not (MSVC++) then best of luck.
Anyway I 100% agree people way, way overuse macros. Very often a static inline function is a better trade-off.
#define SQ(x) x*x
cout << SQ(2) // prints 4 since 2*2 = 4
cout << SQ(1+3) // prints 7 since 1+3*1+3 = 7
Macros are pretty much entirely unnecessary and should be avoided. Compilers inline nowadays, so you don’t really gain anything from using a macro when you could have just made a function that gives you type safety and intuitive behavior. If you are trying to define constants, use const, enum, or enum classes. If you are trying to define multiple versions of the same function, use polymorphism or templates. If you are trying to wrap around arbitrary code, use lambdas.