@@ -734,40 +734,60 @@ auto identity(T&&, U&&... u) -> last_t<U...> {
734734
735735#ifndef DBG_MACRO_DISABLE
736736
737- #define DBG_FOREACH_1 (fn, x ) fn(x)
738- #define DBG_FOREACH_2 (fn, x, ...) fn(x), DBG_FOREACH_1(fn, __VA_ARGS__)
739- #define DBG_FOREACH_3 (fn, x, ...) fn(x), DBG_FOREACH_2(fn, __VA_ARGS__)
740- #define DBG_FOREACH_4 (fn, x, ...) fn(x), DBG_FOREACH_3(fn, __VA_ARGS__)
741- #define DBG_FOREACH_5 (fn, x, ...) fn(x), DBG_FOREACH_4(fn, __VA_ARGS__)
742- #define DBG_FOREACH_6 (fn, x, ...) fn(x), DBG_FOREACH_5(fn, __VA_ARGS__)
743- #define DBG_FOREACH_7 (fn, x, ...) fn(x), DBG_FOREACH_6(fn, __VA_ARGS__)
744- #define DBG_FOREACH_8 (fn, x, ...) fn(x), DBG_FOREACH_7(fn, __VA_ARGS__)
745- #define DBG_FOREACH_9 (fn, x, ...) fn(x), DBG_FOREACH_8(fn, __VA_ARGS__)
746- #define DBG_FOREACH_10 (fn, x, ...) fn(x), DBG_FOREACH_9(fn, __VA_ARGS__)
747- #define DBG_FOREACH_11 (fn, x, ...) fn(x), DBG_FOREACH_10(fn, __VA_ARGS__)
748- #define DBG_FOREACH_12 (fn, x, ...) fn(x), DBG_FOREACH_11(fn, __VA_ARGS__)
749- #define DBG_FOREACH_13 (fn, x, ...) fn(x), DBG_FOREACH_12(fn, __VA_ARGS__)
750- #define DBG_FOREACH_14 (fn, x, ...) fn(x), DBG_FOREACH_13(fn, __VA_ARGS__)
751- #define DBG_FOREACH_15 (fn, x, ...) fn(x), DBG_FOREACH_14(fn, __VA_ARGS__)
752- #define DBG_FOREACH_16 (fn, x, ...) fn(x), DBG_FOREACH_15(fn, __VA_ARGS__)
753- #define DBG_FOREACH_N (_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, \
754- _14, _15, _16, N, ...) \
755- N
756-
757- #define DBG_FOREACH (fn, ...) \
758- DBG_FOREACH_N (__VA_ARGS__, DBG_FOREACH_16, DBG_FOREACH_15, DBG_FOREACH_14, \
759- DBG_FOREACH_13, DBG_FOREACH_12, DBG_FOREACH_11, \
760- DBG_FOREACH_10, DBG_FOREACH_9, DBG_FOREACH_8, DBG_FOREACH_7, \
761- DBG_FOREACH_6, DBG_FOREACH_5, DBG_FOREACH_4, DBG_FOREACH_3, \
762- DBG_FOREACH_2, DBG_FOREACH_1, unused) \
763- (fn, __VA_ARGS__)
737+ // Force expanding argument with commas for MSVC, ref:
738+ // https://stackoverflow.com/questions/35210637/macro-expansion-argument-with-commas
739+ // Note that "args" should be a tuple with parentheses, such as "(e1, e2, ...)".
740+ #define DBG_IDENTITY (x ) x
741+ #define DBG_CALL (fn, args ) DBG_IDENTITY(fn args)
742+
743+ #define DBG_CAT_IMPL (_1, _2 ) _1##_2
744+ #define DBG_CAT (_1, _2 ) DBG_CAT_IMPL(_1, _2)
745+
746+ #define DBG_16TH_IMPL (_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, \
747+ _14, _15, _16, ...) \
748+ _16
749+ #define DBG_16TH (args ) DBG_CALL(DBG_16TH_IMPL, args)
750+ #define DBG_NARG (...) \
751+ DBG_16TH ((__VA_ARGS__, 15 , 14 , 13 , 12 , 11 , 10 , 9 , 8 , 7 , 6 , 5 , 4 , 3 , 2 , 1 , 0 ))
752+
753+ // DBG_VARIADIC_CALL(fn, data, e1, e2, ...) => fn_N(data, (e1, e2, ...))
754+ #define DBG_VARIADIC_CALL (fn, data, ...) \
755+ DBG_CAT (fn##_, DBG_NARG(__VA_ARGS__))(data, (__VA_ARGS__))
756+
757+ // (e1, e2, e3, ...) => e1
758+ #define DBG_HEAD_IMPL (_1, ...) _1
759+ #define DBG_HEAD (args ) DBG_CALL(DBG_HEAD_IMPL, args)
760+
761+ // (e1, e2, e3, ...) => (e2, e3, ...)
762+ #define DBG_TAIL_IMPL (_1, ...) (__VA_ARGS__)
763+ #define DBG_TAIL (args ) DBG_CALL(DBG_TAIL_IMPL, args)
764+
765+ #define DBG_MAP_1 (fn, args ) DBG_CALL(fn, args)
766+ #define DBG_MAP_2 (fn, args ) fn(DBG_HEAD(args)), DBG_MAP_1(fn, DBG_TAIL(args))
767+ #define DBG_MAP_3 (fn, args ) fn(DBG_HEAD(args)), DBG_MAP_2(fn, DBG_TAIL(args))
768+ #define DBG_MAP_4 (fn, args ) fn(DBG_HEAD(args)), DBG_MAP_3(fn, DBG_TAIL(args))
769+ #define DBG_MAP_5 (fn, args ) fn(DBG_HEAD(args)), DBG_MAP_4(fn, DBG_TAIL(args))
770+ #define DBG_MAP_6 (fn, args ) fn(DBG_HEAD(args)), DBG_MAP_5(fn, DBG_TAIL(args))
771+ #define DBG_MAP_7 (fn, args ) fn(DBG_HEAD(args)), DBG_MAP_6(fn, DBG_TAIL(args))
772+ #define DBG_MAP_8 (fn, args ) fn(DBG_HEAD(args)), DBG_MAP_7(fn, DBG_TAIL(args))
773+ #define DBG_MAP_9 (fn, args ) fn(DBG_HEAD(args)), DBG_MAP_8(fn, DBG_TAIL(args))
774+ #define DBG_MAP_10 (fn, args ) fn(DBG_HEAD(args)), DBG_MAP_9(fn, DBG_TAIL(args))
775+ #define DBG_MAP_11 (fn, args ) fn(DBG_HEAD(args)), DBG_MAP_10(fn, DBG_TAIL(args))
776+ #define DBG_MAP_12 (fn, args ) fn(DBG_HEAD(args)), DBG_MAP_11(fn, DBG_TAIL(args))
777+ #define DBG_MAP_13 (fn, args ) fn(DBG_HEAD(args)), DBG_MAP_12(fn, DBG_TAIL(args))
778+ #define DBG_MAP_14 (fn, args ) fn(DBG_HEAD(args)), DBG_MAP_13(fn, DBG_TAIL(args))
779+ #define DBG_MAP_15 (fn, args ) fn(DBG_HEAD(args)), DBG_MAP_14(fn, DBG_TAIL(args))
780+ #define DBG_MAP_16 (fn, args ) fn(DBG_HEAD(args)), DBG_MAP_15(fn, DBG_TAIL(args))
781+
782+ // DBG_MAP(fn, e1, e2, e3, ...) => fn(e1), fn(e2), fn(e3), ...
783+ #define DBG_MAP (fn, ...) DBG_VARIADIC_CALL(DBG_MAP, fn, __VA_ARGS__)
764784
765785#define DBG_STRINGIFY_IMPL (x ) #x
766786#define DBG_STRINGIFY (x ) DBG_STRINGIFY_IMPL(x)
767787
768788#define dbg (...) \
769789 dbg::DebugOutput (__FILE__, __LINE__, __func__) \
770- .print({DBG_FOREACH (DBG_STRINGIFY, __VA_ARGS__)}, __VA_ARGS__)
790+ .print({DBG_MAP (DBG_STRINGIFY, __VA_ARGS__)}, __VA_ARGS__)
771791#else
772792#define dbg (...) dbg::identity(__VA_ARGS__)
773793#endif // DBG_MACRO_DISABLE
0 commit comments