Am 09.09.23 um 00:28 schrieb René Scharfe: > Am 07.09.23 um 22:40 schrieb Jeff King: > > I was thinking more about something like the solutions discussed at > https://stackoverflow.com/questions/47674663/variable-arguments-inside-a-macro. > It allows selecting variants based on argument count. > > That could look like this (untested except on https://godbolt.org/; the > EVALs are needed for MSVC for some reason): > > #define OPT_INTEGER_FULL(s, l, v, h, f, d) { \ > .type = OPTION_INTEGER, \ > .short_name = (s), \ > .long_name = (l), \ > .value = (v), \ > .argh = N_("n"), \ > .help = (h), \ > .flags = (f), \ > .defval = (d), \ > } > #define OPT_INTEGER_4(s, l, v, h) \ > OPT_INTEGER_FULL(s, l, v, h, 0, 0) > #define OPT_INTEGER_5(s, l, v, h, f) \ > OPT_INTEGER_FULL(s, l, v, h, f, 0) > #define OPT_INTEGER_6(s, l, v, h, f, d) \ > OPT_INTEGER_FULL(s, l, v, h, (f) | PARSE_OPT_OPTARG, d) > #define EVAL(x) x > #define SEVENTH(_1, _2, _3, _4, _5, _6, x, ...) x > #define OPT_INTEGER(...) \ > EVAL(EVAL(SEVENTH(__VA_ARGS__, OPT_INTEGER_6, OPT_INTEGER_5, OPT_INTEGER_4, 0))(__VA_ARGS__)) > > So OPT_INTEGER(s, l, v, h) would be the same as before. Add an argument > and it becomes current OPT_INTEGER_F, add another one and it acts as > your _OPTARG_F variant. Should we actually do something like that? Probably not. At least it doesn't help with my goals of simplicity and safety. (I get sidetracked so easily..) >> So yeah, I think you'd really want a separate macro. The combinations >> start to add up (or multiply up, if you prefer ;) ). They _could_ be >> generated mechanically, I think, as they can all be implemented in terms >> of a master macro that knows about all features: >> >> #define OPT_BOOL_F(s, l, v, h, f) OPT_BOOL_ALL(s, l, v, h, f, 0) >> #define OPT_BOOL(s, l, v, h, f) OPT_BOOL_F(s, l, v, h, 0) > > The "f" arg needs to go... > >> #define OPT_BOOL_OPTARG_F(s, l, v, h, arg) OPT_BOOL_ALL(s, l, v, h, f | PARSE_OPT_OPTARG, arg) > > ... here, possibly. > >> #define OPT_BOOL_OPTARG(s, l, v, h, arg) OPT_BOOL_OPTARG_F(s, l, v, h, 0, arg) Or we could use designated initializers directly. It would improve readability at the cost of some verbosity. We could make it a bit less verbose by by setting some flags implicitly based on type (e.g. set PARSE_OPT_OPTARG if defval is set for an OPTION_INTEGER option). René