Skip to content

Commit 12073d5

Browse files
ShikChensharkdp
authored andcommitted
Fix variadic macros for MSVC
1 parent dce0091 commit 12073d5

File tree

2 files changed

+52
-32
lines changed

2 files changed

+52
-32
lines changed

dbg.h

Lines changed: 48 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -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

tests/demo.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ int main() {
8484
std::vector<bool> vec_bools{true, true, false, false, false, true, false};
8585
dbg(vec_bools);
8686

87-
dbg(std::vector<int>{0, 1, 0, 1});
87+
dbg((std::vector<int>{0, 1, 0, 1}));
8888

8989
const std::array<int, 2> dummy_array{{0, 4}};
9090
dbg(dummy_array);
@@ -111,14 +111,14 @@ int main() {
111111
dbg(dbg::bin(static_cast<uint8_t>(negative_five)));
112112

113113
dbg("====== std::tuple and std::pair");
114-
dbg(std::tuple<std::string, int, float>{"Hello", 7, 3.14f});
115-
dbg(std::pair<std::string, int>{"Hello", 7});
114+
dbg((std::tuple<std::string, int, float>{"Hello", 7, 3.14f}));
115+
dbg((std::pair<std::string, int>{"Hello", 7}));
116116

117117
#if DBG_MACRO_CXX_STANDARD >= 17
118118
dbg("====== Sum types");
119119
dbg(std::make_optional<bool>(false));
120120

121-
dbg(std::variant<int, std::string>{"test"});
121+
dbg((std::variant<int, std::string>{"test"}));
122122
#endif
123123

124124
dbg("====== function name tests");

0 commit comments

Comments
 (0)