Skip to content

Commit eb03303

Browse files
authored
Replace the dummy arg from compound initializers in the C API with more macro magic (#4696)
The dummy argument {fmt_int} was there as a workaround for MSVC and to avoid needing to rely on another GCC extension for zero-size arrays. Use macro magic similar to FMT_NARG() instead that replaces the problematic zero-size array with NULL. In order to avoid a quadratic number of expansions, defer creating the mapped argument list until after selection of whether to use NULL or the fmt_arg array. Signed-off-by: Ferdinand Bachmann <ferdinand.bachmann@yrlf.at>
1 parent ab4f661 commit eb03303

File tree

1 file changed

+17
-6
lines changed

1 file changed

+17
-6
lines changed

include/fmt/fmt-c.h

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ typedef enum {} fmt_signed_char;
130130
# define FMT_NARG_(_id, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, \
131131
_13, _14, _15, _16, N, ...) \
132132
N
133-
# define FMT_NARG(...) \
133+
# define FMT_NARG(_dummy, ...) \
134134
FMT_NARG_(dummy, ##__VA_ARGS__, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, \
135135
4, 3, 2, 1, 0)
136136

@@ -166,13 +166,24 @@ typedef enum {} fmt_signed_char;
166166
f(n), f(o), f(p), f(q)
167167

168168
# define FMT_MAP(f, ...) \
169-
FMT_CAT(FMT_MAP_, FMT_NARG(__VA_ARGS__))(f, ##__VA_ARGS__)
169+
FMT_CAT(FMT_MAP_, FMT_NARG(, ##__VA_ARGS__))(f, ##__VA_ARGS__)
170+
171+
// select between two expressions depending on whether __VA_ARGS__ is empty
172+
// expands to e if __VA_ARGS__ is empty and n otherwise
173+
# define FMT_VA_SELECT(e, n, ...) \
174+
FMT_NARG_(dummy, ##__VA_ARGS__, n, n, n, n, n, n, n, n, n, n, n, n, n, n, \
175+
n, n, e)
176+
177+
# define FMT_MAKE_NULL(...) NULL
178+
# define FMT_MAKE_ARGLIST(...) \
179+
(fmt_arg[]) { FMT_MAP(FMT_MAKE_ARG, ##__VA_ARGS__) }
180+
# define FMT_EXPAND(v) v
170181

171182
# define fmt_format(buffer, size, fmt, ...) \
172-
fmt_vformat( \
173-
(buffer), (size), (fmt), \
174-
(fmt_arg[]){{fmt_int}, FMT_MAP(FMT_MAKE_ARG, ##__VA_ARGS__)} + 1, \
175-
FMT_NARG(__VA_ARGS__))
183+
fmt_vformat((buffer), (size), (fmt), \
184+
FMT_EXPAND(FMT_VA_SELECT(FMT_MAKE_NULL, FMT_MAKE_ARGLIST, \
185+
##__VA_ARGS__)(__VA_ARGS__)), \
186+
FMT_NARG(, ##__VA_ARGS__))
176187

177188
#endif // __cplusplus
178189

0 commit comments

Comments
 (0)