6 ms·
Nope! In general, that can be a problem, but not for this specific technique: $ cpp -P void plot(float xlo, float xhi, float ylo, float yhi, float xinc, fl
by mananaysiempre 2y ago
Nope! In general, that can be a problem, but not for this specific technique:
$ cpp -P
void plot(float xlo, float xhi, float ylo, float yhi, float xinc, float yinc);
struct plot_a { float xlo, xhi, ylo, yhi, xinc, yinc; };
static inline void plot_i(struct plot_a _a) {
// inline thunk to allow arguments to go in registers
plot(_a.xlo, _a.xhi, _a.ylo, _a.yho, _a.xinc, _a.yinc);
}
#define plot(...) (plot_i((struct plot_a){ __VA_ARGS__ }))
plot((myfoo){x,y})
plot(.yinc=(myfoo){x,y})
^D
[...]
(plot_i((struct plot_a){ (myfoo){x,y} }))
(plot_i((struct plot_a){ .yinc=(myfoo){x,y} }))
You could argue this is excessively clever, but when you need it, you really need it, so it could deserve known idiom status in the right situation.
- ori_b 2y ago> You could argue this is excessively clever, but when you need it, you really need it I've probably written millions of lines of C so far, and I don't think I have ever needed it.
- mananaysiempre 2y agoThe usual workarounds are a stateful API (e.g. Cairo, OpenGL, or Windows GDI), passing a structure explicitly (oodles of examples in Win32, e.g. RegisterClass or GetOpenFileName), or a twiddling an object that’s actually just a structure dressed up in accessor methods (IOpenFileDialog). There could be reasons to use one of those still (e.g. extensibility while keeping a compatible ABI, as in setsockopt, pthread_attr_*, or arguably posix_spawnattr_*). But sometimes you really do need a finite, well-known but just plain large number of parameters that mostly have reasonable defaults. Old-style 2D APIs to draw and/or stroke a shape (or even just a rectangle) are the classic example. Plotting libraries (in all languages) are also prone to this. It does seem like these situations are mostly endemic to specific application areas—graphics of all kinds first of all—but that doesn’t make them not exist. If you don’t want to use function-like macros for anything ever even if this particular one works, that’s a valid position. But it does work, it does solve a real problem, and it is less awkward at the use site than the alternatives.
- ori_b 2y agoWith large numbers of parameters, it's almost always more readable to use a config struct. Especially since often, you want to collect configuration from multiple sources, and incrementally initializing a struct that way is helpful.