pw_preprocessor: Improve macro arg handling
- Add PW_LAST_ARG, PW_DROP_LAST_ARG, and PW_DROP_LAST_ARG_IF_EMPTY.
- Reimplement PW_COMMA_ARGS and PW_DELEGATE_BY_ARG_COUNT in terms of
these new macros. This makes macros built with these more robust.
- Add a test for PW_COMMA_ARGS that demonstrates why it should not be
used when invoking a function-like macro.
Change-Id: I862f70623d53fdd7eee1440f91161981e12ce892
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/16283
Reviewed-by: Keir Mierle <keir@google.com>
Commit-Queue: Keir Mierle <keir@google.com>
diff --git a/pw_preprocessor/BUILD b/pw_preprocessor/BUILD
index 1b937ce..439e383 100644
--- a/pw_preprocessor/BUILD
+++ b/pw_preprocessor/BUILD
@@ -24,6 +24,7 @@
pw_cc_library(
name = "pw_preprocessor",
+ srcs = ["public/pw_preprocessor/internal/arg_count_impl.h"],
hdrs = glob(["public/pw_preprocessor/*.h"]),
includes = ["public"],
)
diff --git a/pw_preprocessor/BUILD.gn b/pw_preprocessor/BUILD.gn
index 0c43ec0..b88ba32 100644
--- a/pw_preprocessor/BUILD.gn
+++ b/pw_preprocessor/BUILD.gn
@@ -31,6 +31,7 @@
"public/pw_preprocessor/macro_arg_count.h",
"public/pw_preprocessor/util.h",
]
+ sources = [ "public/pw_preprocessor/internal/arg_count_impl.h" ]
}
pw_doc_group("docs") {
diff --git a/pw_preprocessor/macro_arg_count_test.cc b/pw_preprocessor/macro_arg_count_test.cc
index f450b24..7398e14 100644
--- a/pw_preprocessor/macro_arg_count_test.cc
+++ b/pw_preprocessor/macro_arg_count_test.cc
@@ -32,13 +32,13 @@
// Test how the macro handles whitespace and comments.
// clang-format off
- static_assert(PW_HAS_ARGS( ) == 0); // NOLINT
+ static_assert(PW_HAS_ARGS( ) == 0);
static_assert(PW_HAS_ARGS(
- ) == 0); // NOLINT
+ ) == 0);
static_assert(PW_HAS_ARGS(
// wow
// This is a comment.
- ) == 0); // NOLINT
+ ) == 0);
// clang-format on
static_assert(PW_EMPTY_ARGS() == 1);
@@ -51,13 +51,13 @@
TEST(HasArgs, WithArguments) {
static_assert(PW_HAS_ARGS(()) == 1);
static_assert(PW_HAS_ARGS(0) == 1);
- static_assert(PW_HAS_ARGS(, ) == 1); // NOLINT
+ static_assert(PW_HAS_ARGS(, ) == 1);
static_assert(PW_HAS_ARGS(a, b, c) == 1);
static_assert(PW_HAS_ARGS(PW_HAS_ARGS) == 1);
static_assert(PW_HAS_ARGS(PW_HAS_ARGS()) == 1);
static_assert(PW_EMPTY_ARGS(0) == 0);
- static_assert(PW_EMPTY_ARGS(, ) == 0); // NOLINT
+ static_assert(PW_EMPTY_ARGS(, ) == 0);
static_assert(PW_EMPTY_ARGS(a, b, c) == 0);
static_assert(PW_EMPTY_ARGS(PW_HAS_ARGS) == 0);
static_assert(PW_EMPTY_ARGS(PW_HAS_ARGS()) == 0);
@@ -120,31 +120,66 @@
static_assert(COUNT_ARGS_TEMPLATE(int, int, int, EMPTY_ARG) == 3);
}
+// This test demonstrates that PW_COMMA_ARGS behaves unexpectedly when it is
+// used when invoking another macro. DO NOT use PW_COMMA_ARGS when invoking
+// another macro!
+#define BAD_DEMO(fmt, ...) _BAD_DEMO_ADD_123(fmt PW_COMMA_ARGS(__VA_ARGS__))
+
+#define _BAD_DEMO_ADD_123(fmt, ...) \
+ _BAD_DEMO_STRINGIFY("%d: " fmt, 123 PW_COMMA_ARGS(__VA_ARGS__))
+
+#define _BAD_DEMO_STRINGIFY(...) PW_STRINGIFY(__VA_ARGS__)
+
+TEST(CommaVarargs, MisbehavesWithMacroToMacroUse) {
+// Disable this EXPECT for now; it breaks on ARM/discovery due to the
+// preprocessor adding space before the comma after Hello World:
+//
+// "Hello world" , 123
+//
+// rather than (as on host builds):
+//
+// "Hello world", 123
+//
+// TODO(keir): Fix the inconsistency and restore this expectation.
+#if 0
+ // With no additional arguments, everything is OK
+ EXPECT_STREQ(BAD_DEMO("Hello world"), R"("%d: " "Hello world", 123)");
+#endif
+
+ // If there is an additional argument, the order is incorrect! The 123
+ // argument should go before the "world?" argument, but it is inserted after.
+ // This would be a compilation error if these arguments were passed to printf.
+ // What's worse is that this can silently fail if the arguments happen to be
+ // compatible types.
+ EXPECT_STREQ(BAD_DEMO("Hello %s", "world?"),
+ R"("%d: " "Hello %s" , "world?", 123)");
+}
+
TEST(CountArgs, Zero) {
static_assert(PW_ARG_COUNT() == 0);
static_assert(PW_ARG_COUNT(/**/) == 0);
static_assert(PW_ARG_COUNT(/* uhm, hi */) == 0);
// clang-format off
- static_assert(PW_ARG_COUNT( ) == 0); // NOLINT
+ static_assert(PW_ARG_COUNT( ) == 0);
static_assert(PW_ARG_COUNT(
- ) == 0); // NOLINT
+ ) == 0);
static_assert(PW_ARG_COUNT(
// wow
// This is a comment.
- ) == 0); // NOLINT
+ ) == 0);
// clang-format on
}
TEST(CountArgs, Commas) {
// clang-format off
- static_assert(PW_ARG_COUNT(,) == 2); // NOLINT
- static_assert(PW_ARG_COUNT(,,) == 3); // NOLINT
- static_assert(PW_ARG_COUNT(,,,) == 4); // NOLINT
+ static_assert(PW_ARG_COUNT(,) == 2);
+ static_assert(PW_ARG_COUNT(,,) == 3);
+ static_assert(PW_ARG_COUNT(,,,) == 4);
// clang-format on
- static_assert(PW_ARG_COUNT(, ) == 2); // NOLINT
- static_assert(PW_ARG_COUNT(, , ) == 3); // NOLINT
- static_assert(PW_ARG_COUNT(, , , ) == 4); // NOLINT
+ static_assert(PW_ARG_COUNT(, ) == 2);
+ static_assert(PW_ARG_COUNT(, , ) == 3);
+ static_assert(PW_ARG_COUNT(, , , ) == 4);
}
TEST(CountArgs, Parentheses) {
@@ -153,10 +188,78 @@
static_assert(PW_ARG_COUNT((1, 2, 3), (1, 2, 3, 4)) == 2);
static_assert(PW_ARG_COUNT((), ()) == 2);
static_assert(PW_ARG_COUNT((-), (o)) == 2);
- static_assert(PW_ARG_COUNT((, , (, , ), ), (123, 4)) == 2); // NOLINT
+ static_assert(PW_ARG_COUNT((, , (, , ), ), (123, 4)) == 2);
static_assert(PW_ARG_COUNT(1, (2, 3, 4), (<5, 6>)) == 3);
}
+template <typename... Args>
+constexpr size_t FunctionArgCount(Args...) {
+ return sizeof...(Args);
+}
+
+static_assert(FunctionArgCount() == 0);
+static_assert(FunctionArgCount(1) == 1);
+static_assert(FunctionArgCount(1, 2) == 2);
+
+TEST(CountFunctionArgs, NonEmptyLastArg) {
+ static_assert(PW_FUNCTION_ARG_COUNT(a) == 1);
+ static_assert(PW_FUNCTION_ARG_COUNT(1, 2) == 2);
+ static_assert(PW_FUNCTION_ARG_COUNT(1, 2, 3) == 3);
+}
+
+TEST(CountFunctionArgs, EmptyLastArg) {
+ static_assert(PW_FUNCTION_ARG_COUNT() == 0);
+ static_assert(PW_FUNCTION_ARG_COUNT(a, ) == 1);
+ static_assert(PW_FUNCTION_ARG_COUNT(1, 2, ) == 2);
+ static_assert(PW_FUNCTION_ARG_COUNT(1, 2, 3, ) == 3);
+
+ static_assert(PW_FUNCTION_ARG_COUNT(a, EMPTY_ARG) == 1);
+ static_assert(PW_FUNCTION_ARG_COUNT(1, 2, EMPTY_ARG) == 2);
+ static_assert(PW_FUNCTION_ARG_COUNT(1, 2, 3, EMPTY_ARG) == 3);
+}
+
+constexpr const char* Value(const char* str = nullptr) { return str; }
+
+TEST(LastArg, NonEmptyLastArg) {
+ constexpr const char* last = "last!";
+ static_assert(Value(PW_LAST_ARG(last)) == last);
+ static_assert(Value(PW_LAST_ARG(1, last)) == last);
+ static_assert(Value(PW_LAST_ARG(1, 2, last)) == last);
+}
+
+TEST(LastArg, EmptyLastArg) {
+ static_assert(Value(PW_LAST_ARG()) == nullptr);
+ static_assert(Value(PW_LAST_ARG(1, )) == nullptr);
+ static_assert(Value(PW_LAST_ARG(1, 2, )) == nullptr);
+ static_assert(Value(PW_LAST_ARG(1, 2, 3, )) == nullptr);
+}
+
+TEST(DropLastArg, NonEmptyLastArg) {
+ static_assert(FunctionArgCount(PW_DROP_LAST_ARG(1)) == 0);
+ static_assert(FunctionArgCount(PW_DROP_LAST_ARG(1, 2)) == 1);
+ static_assert(FunctionArgCount(PW_DROP_LAST_ARG(1, 2, 3)) == 2);
+}
+
+TEST(DropLastArg, EmptyLastArg) {
+ static_assert(FunctionArgCount(PW_DROP_LAST_ARG()) == 0);
+ static_assert(FunctionArgCount(PW_DROP_LAST_ARG(1, )) == 1);
+ static_assert(FunctionArgCount(PW_DROP_LAST_ARG(1, 2, )) == 2);
+ static_assert(FunctionArgCount(PW_DROP_LAST_ARG(1, 2, 3, )) == 3);
+}
+
+TEST(DropLastArgIfEmpty, NonEmptyLastArg) {
+ static_assert(FunctionArgCount(PW_DROP_LAST_ARG_IF_EMPTY(1)) == 1);
+ static_assert(FunctionArgCount(PW_DROP_LAST_ARG_IF_EMPTY(1, 2)) == 2);
+ static_assert(FunctionArgCount(PW_DROP_LAST_ARG_IF_EMPTY(1, 2, 3)) == 3);
+}
+
+TEST(DropLastArgIfEmpty, EmptyLastArg) {
+ static_assert(FunctionArgCount(PW_DROP_LAST_ARG_IF_EMPTY()) == 0);
+ static_assert(FunctionArgCount(PW_DROP_LAST_ARG_IF_EMPTY(1, )) == 1);
+ static_assert(FunctionArgCount(PW_DROP_LAST_ARG_IF_EMPTY(1, 2, )) == 2);
+ static_assert(FunctionArgCount(PW_DROP_LAST_ARG_IF_EMPTY(1, 2, 3, )) == 3);
+}
+
#define SOME_VARIADIC_MACRO(...) PW_ARG_COUNT(__VA_ARGS__)
#define ANOTHER_VARIADIC_MACRO(arg, ...) SOME_VARIADIC_MACRO(__VA_ARGS__)
@@ -192,75 +295,75 @@
Python 3 code:
for i in range(64 + 1):
args = [f'X{x}' for x in range(1, i + 1)]
- print(f' static_assert(PW_ARG_COUNT({", ".join(args)}) == {i}) // NOLINT')
+ print(f' static_assert(PW_ARG_COUNT({", ".join(args)}) == {i}) ')
*/
TEST(CountArgs, AllSupported) {
// clang-format off
- static_assert(PW_ARG_COUNT() == 0); // NOLINT
- static_assert(PW_ARG_COUNT(X1) == 1); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2) == 2); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3) == 3); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4) == 4); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5) == 5); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6) == 6); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7) == 7); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8) == 8); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9) == 9); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10) == 10); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11) == 11); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12) == 12); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13) == 13); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14) == 14); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15) == 15); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16) == 16); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17) == 17); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18) == 18); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19) == 19); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20) == 20); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21) == 21); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22) == 22); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23) == 23); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24) == 24); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25) == 25); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26) == 26); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27) == 27); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28) == 28); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29) == 29); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30) == 30); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31) == 31); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32) == 32); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33) == 33); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34) == 34); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35) == 35); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36) == 36); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37) == 37); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38) == 38); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39) == 39); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40) == 40); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41) == 41); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42) == 42); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43) == 43); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44) == 44); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45) == 45); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46) == 46); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47) == 47); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48) == 48); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49) == 49); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50) == 50); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51) == 51); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52) == 52); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52, X53) == 53); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52, X53, X54) == 54); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52, X53, X54, X55) == 55); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52, X53, X54, X55, X56) == 56); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52, X53, X54, X55, X56, X57) == 57); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52, X53, X54, X55, X56, X57, X58) == 58); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52, X53, X54, X55, X56, X57, X58, X59) == 59); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52, X53, X54, X55, X56, X57, X58, X59, X60) == 60); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52, X53, X54, X55, X56, X57, X58, X59, X60, X61) == 61); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52, X53, X54, X55, X56, X57, X58, X59, X60, X61, X62) == 62); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52, X53, X54, X55, X56, X57, X58, X59, X60, X61, X62, X63) == 63); // NOLINT
- static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52, X53, X54, X55, X56, X57, X58, X59, X60, X61, X62, X63, X64) == 64); // NOLINT
+ static_assert(PW_ARG_COUNT() == 0);
+ static_assert(PW_ARG_COUNT(X1) == 1);
+ static_assert(PW_ARG_COUNT(X1, X2) == 2);
+ static_assert(PW_ARG_COUNT(X1, X2, X3) == 3);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4) == 4);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5) == 5);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6) == 6);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7) == 7);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8) == 8);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9) == 9);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10) == 10);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11) == 11);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12) == 12);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13) == 13);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14) == 14);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15) == 15);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16) == 16);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17) == 17);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18) == 18);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19) == 19);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20) == 20);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21) == 21);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22) == 22);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23) == 23);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24) == 24);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25) == 25);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26) == 26);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27) == 27);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28) == 28);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29) == 29);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30) == 30);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31) == 31);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32) == 32);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33) == 33);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34) == 34);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35) == 35);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36) == 36);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37) == 37);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38) == 38);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39) == 39);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40) == 40);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41) == 41);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42) == 42);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43) == 43);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44) == 44);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45) == 45);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46) == 46);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47) == 47);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48) == 48);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49) == 49);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50) == 50);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51) == 51);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52) == 52);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52, X53) == 53);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52, X53, X54) == 54);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52, X53, X54, X55) == 55);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52, X53, X54, X55, X56) == 56);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52, X53, X54, X55, X56, X57) == 57);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52, X53, X54, X55, X56, X57, X58) == 58);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52, X53, X54, X55, X56, X57, X58, X59) == 59);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52, X53, X54, X55, X56, X57, X58, X59, X60) == 60);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52, X53, X54, X55, X56, X57, X58, X59, X60, X61) == 61);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52, X53, X54, X55, X56, X57, X58, X59, X60, X61, X62) == 62);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52, X53, X54, X55, X56, X57, X58, X59, X60, X61, X62, X63) == 63);
+ static_assert(PW_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, X32, X33, X34, X35, X36, X37, X38, X39, X40, X41, X42, X43, X44, X45, X46, X47, X48, X49, X50, X51, X52, X53, X54, X55, X56, X57, X58, X59, X60, X61, X62, X63, X64) == 64);
// clang-format on
}
diff --git a/pw_preprocessor/public/pw_preprocessor/internal/arg_count_impl.h b/pw_preprocessor/public/pw_preprocessor/internal/arg_count_impl.h
new file mode 100644
index 0000000..7cd822a
--- /dev/null
+++ b/pw_preprocessor/public/pw_preprocessor/internal/arg_count_impl.h
@@ -0,0 +1,109 @@
+// Copyright 2020 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+#pragma once
+
+// Expands to the passed arguments.
+#define _PW_EXPAND(...) __VA_ARGS__
+
+// If-like macro for internal use.
+#define _PW_IF(boolean, true_expr, false_expr) \
+ _PW_PASTE2(_PW_IF_, boolean)(true_expr, false_expr)
+
+#define _PW_IF_0(true_expr, false_expr) false_expr
+#define _PW_IF_1(true_expr, false_expr) true_expr
+
+// Token pasting macro that doesn't rely on concat.h
+#define _PW_PASTE2(a1, a2) _PW_PASTE2_EXPANDED(a1, a2)
+#define _PW_PASTE2_EXPANDED(a1, a2) _PW_PASTE2_IMPL(a1, a2)
+#define _PW_PASTE2_IMPL(a1, a2) a1##a2
+
+/*
+for i in range(2, 33):
+ args = ', '.join(f'a{arg}' for arg in range(1, i))
+ print(f'#define _PW_LAST_ARG_{i}({args}, a{i}) a{i}')
+*/
+// clang-format off
+#define _PW_LAST_ARG_0()
+#define _PW_LAST_ARG_1(a1) a1
+#define _PW_LAST_ARG_2(a1, a2) a2
+#define _PW_LAST_ARG_3(a1, a2, a3) a3
+#define _PW_LAST_ARG_4(a1, a2, a3, a4) a4
+#define _PW_LAST_ARG_5(a1, a2, a3, a4, a5) a5
+#define _PW_LAST_ARG_6(a1, a2, a3, a4, a5, a6) a6
+#define _PW_LAST_ARG_7(a1, a2, a3, a4, a5, a6, a7) a7
+#define _PW_LAST_ARG_8(a1, a2, a3, a4, a5, a6, a7, a8) a8
+#define _PW_LAST_ARG_9(a1, a2, a3, a4, a5, a6, a7, a8, a9) a9
+#define _PW_LAST_ARG_10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) a10
+#define _PW_LAST_ARG_11(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) a11
+#define _PW_LAST_ARG_12(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) a12
+#define _PW_LAST_ARG_13(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) a13
+#define _PW_LAST_ARG_14(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) a14
+#define _PW_LAST_ARG_15(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) a15
+#define _PW_LAST_ARG_16(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) a16
+#define _PW_LAST_ARG_17(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) a17
+#define _PW_LAST_ARG_18(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) a18
+#define _PW_LAST_ARG_19(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) a19
+#define _PW_LAST_ARG_20(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) a20
+#define _PW_LAST_ARG_21(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21) a21
+#define _PW_LAST_ARG_22(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22) a22
+#define _PW_LAST_ARG_23(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23) a23
+#define _PW_LAST_ARG_24(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24) a24
+#define _PW_LAST_ARG_25(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25) a25
+#define _PW_LAST_ARG_26(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26) a26
+#define _PW_LAST_ARG_27(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27) a27
+#define _PW_LAST_ARG_28(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28) a28
+#define _PW_LAST_ARG_29(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29) a29
+#define _PW_LAST_ARG_30(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30) a30
+#define _PW_LAST_ARG_31(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31) a31
+#define _PW_LAST_ARG_32(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32) a32
+
+/*
+for i in range(2, 33):
+ args = ', '.join(f'a{arg}' for arg in range(1, i))
+ print(f'#define _PW_DROP_LAST_ARG_{i}({args}, a{i}) {args}')
+*/
+#define _PW_DROP_LAST_ARG_0()
+#define _PW_DROP_LAST_ARG_1(a1)
+#define _PW_DROP_LAST_ARG_2(a1, a2) a1
+#define _PW_DROP_LAST_ARG_3(a1, a2, a3) a1, a2
+#define _PW_DROP_LAST_ARG_4(a1, a2, a3, a4) a1, a2, a3
+#define _PW_DROP_LAST_ARG_5(a1, a2, a3, a4, a5) a1, a2, a3, a4
+#define _PW_DROP_LAST_ARG_6(a1, a2, a3, a4, a5, a6) a1, a2, a3, a4, a5
+#define _PW_DROP_LAST_ARG_7(a1, a2, a3, a4, a5, a6, a7) a1, a2, a3, a4, a5, a6
+#define _PW_DROP_LAST_ARG_8(a1, a2, a3, a4, a5, a6, a7, a8) a1, a2, a3, a4, a5, a6, a7
+#define _PW_DROP_LAST_ARG_9(a1, a2, a3, a4, a5, a6, a7, a8, a9) a1, a2, a3, a4, a5, a6, a7, a8
+#define _PW_DROP_LAST_ARG_10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) a1, a2, a3, a4, a5, a6, a7, a8, a9
+#define _PW_DROP_LAST_ARG_11(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) a1, a2, a3, a4, a5, a6, a7, a8, a9, a10
+#define _PW_DROP_LAST_ARG_12(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11
+#define _PW_DROP_LAST_ARG_13(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12
+#define _PW_DROP_LAST_ARG_14(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13
+#define _PW_DROP_LAST_ARG_15(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14
+#define _PW_DROP_LAST_ARG_16(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15
+#define _PW_DROP_LAST_ARG_17(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16
+#define _PW_DROP_LAST_ARG_18(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17
+#define _PW_DROP_LAST_ARG_19(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18
+#define _PW_DROP_LAST_ARG_20(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19
+#define _PW_DROP_LAST_ARG_21(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21) a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20
+#define _PW_DROP_LAST_ARG_22(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22) a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21
+#define _PW_DROP_LAST_ARG_23(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23) a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22
+#define _PW_DROP_LAST_ARG_24(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24) a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23
+#define _PW_DROP_LAST_ARG_25(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25) a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24
+#define _PW_DROP_LAST_ARG_26(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26) a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25
+#define _PW_DROP_LAST_ARG_27(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27) a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26
+#define _PW_DROP_LAST_ARG_28(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28) a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27
+#define _PW_DROP_LAST_ARG_29(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29) a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28
+#define _PW_DROP_LAST_ARG_30(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30) a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29
+#define _PW_DROP_LAST_ARG_31(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31) a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30
+#define _PW_DROP_LAST_ARG_32(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32) a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31
+// clang-format on
diff --git a/pw_preprocessor/public/pw_preprocessor/macro_arg_count.h b/pw_preprocessor/public/pw_preprocessor/macro_arg_count.h
index f617f22..7da4c6a 100644
--- a/pw_preprocessor/public/pw_preprocessor/macro_arg_count.h
+++ b/pw_preprocessor/public/pw_preprocessor/macro_arg_count.h
@@ -17,6 +17,7 @@
#pragma once
#include "pw_preprocessor/boolean.h"
+#include "pw_preprocessor/internal/arg_count_impl.h"
// PW_ARG_COUNT counts the number of arguments it was called with. It evalulates
// to an integer literal in the range 0 to 64. Counting more than 64 arguments
@@ -42,6 +43,35 @@
24, 23, 22, 21, 20, 19, 18, 17, \
16, 15, 14, 13, 12, 11, 10, 9, \
8, 7, 6, 5, 4, 3, 2, PW_HAS_ARGS(__VA_ARGS__))
+// clang-format on
+
+// Argument count for using with a C/C++ function or template parameter list.
+// The difference from PW_MACRO_ARG_COUNT is that the last argument is not
+// counted if it is empty. This makes it easier to drop the final comma when
+// expanding to C/C++ code.
+#define PW_FUNCTION_ARG_COUNT(...) \
+ _PW_FUNCTION_ARG_COUNT(PW_LAST_ARG(__VA_ARGS__), __VA_ARGS__)
+
+#define _PW_FUNCTION_ARG_COUNT(last_arg, ...) \
+ _PW_PASTE2(_PW_FUNCTION_ARG_COUNT_, PW_EMPTY_ARGS(last_arg))(__VA_ARGS__)
+
+#define _PW_FUNCTION_ARG_COUNT_0 PW_ARG_COUNT
+#define _PW_FUNCTION_ARG_COUNT_1(...) \
+ PW_ARG_COUNT(PW_DROP_LAST_ARG(__VA_ARGS__))
+
+// Evaluates to the last argument in the provided arguments.
+#define PW_LAST_ARG(...) \
+ _PW_PASTE2(_PW_LAST_ARG_, PW_ARG_COUNT(__VA_ARGS__))(__VA_ARGS__)
+
+// Evaluates to the provided arguments, excluding the final argument.
+#define PW_DROP_LAST_ARG(...) \
+ _PW_PASTE2(_PW_DROP_LAST_ARG_, PW_ARG_COUNT(__VA_ARGS__))(__VA_ARGS__)
+
+// Evaluates to the provided arguments excluding the final argument..
+#define PW_DROP_LAST_ARG_IF_EMPTY(...) \
+ _PW_IF( \
+ PW_EMPTY_ARGS(PW_LAST_ARG(__VA_ARGS__)), PW_DROP_LAST_ARG, _PW_EXPAND) \
+ (__VA_ARGS__)
// Expands to 1 if one or more arguments are provided, 0 otherwise.
#define PW_HAS_ARGS(...) PW_NOT(PW_EMPTY_ARGS(__VA_ARGS__))
@@ -69,12 +99,14 @@
// whether any arguments were passed in.
//
// C++20 introduces __VA_OPT__, which would greatly simplify this macro.
-#define PW_EMPTY_ARGS(...) \
+#define PW_EMPTY_ARGS(...) \
_PW_HAS_NO_ARGS(_PW_HAS_COMMA(__VA_ARGS__), \
_PW_HAS_COMMA(_PW_MAKE_COMMA_IF_CALLED __VA_ARGS__), \
_PW_HAS_COMMA(__VA_ARGS__()), \
_PW_HAS_COMMA(_PW_MAKE_COMMA_IF_CALLED __VA_ARGS__()))
+// clang-format off
+
#define _PW_HAS_COMMA(...) \
_PW_ARG_COUNT_IMPL(__VA_ARGS__, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
@@ -94,6 +126,7 @@
count
// clang-format on
+
#define _PW_HAS_NO_ARGS(a1, a2, a3, a4) \
_PW_HAS_COMMA(_PW_PASTE_RESULTS(a1, a2, a3, a4))
#define _PW_PASTE_RESULTS(a1, a2, a3, a4) _PW_HAS_COMMA_CASE_##a1##a2##a3##a4
@@ -110,7 +143,9 @@
// This is a more flexible, standard-compliant version of ##__VA_ARGS__. Unlike
// ##__VA_ARGS__, this can be used to eliminate an unwanted comma when
// __VA_ARGS__ expands to an empty argument because an outer macro was called
-// with __VA_ARGS__ instead of ##__VA_ARGS__.
+// with __VA_ARGS__ instead of ##__VA_ARGS__. Also, since PW_COMMA_ARGS drops
+// the last argument if it is empty, both MY_MACRO(1, 2) and MY_MACRO(1, 2, )
+// can work correctly.
//
// PW_COMMA_ARGS must NOT be used to conditionally include a comma when invoking
// a macro from another macro. PW_COMMA_ARGS only functions correctly when the
@@ -132,69 +167,11 @@
#define NESTED_MACRO(fmt, ...) \
printf(fmt PW_COMMA_ARGS(__VA_ARGS__)) // PW_COMMA_ARGS is OK here
*/
-#define PW_COMMA_ARGS(...) \
- _PW_COMMA_ARGS(PW_ARG_COUNT(__VA_ARGS__), __VA_ARGS__)
-#define _PW_COMMA_ARGS(count, ...) _PW_COMMA_ARGS_X(count, __VA_ARGS__)
-#define _PW_COMMA_ARGS_X(count, ...) _PW_COMMA_ARGS_##count(__VA_ARGS__)
+#define PW_COMMA_ARGS(...) \
+ _PW_IF(PW_EMPTY_ARGS(__VA_ARGS__), _PW_EXPAND, _PW_COMMA_ARGS) \
+ (PW_DROP_LAST_ARG_IF_EMPTY(__VA_ARGS__))
-// Expand PW_COMMA_ARGS to a macro for each number of arguments. This makes it
-// possible to omit the final argument if it is empty. For example, for the
-// following macro:
-//
-// #define MY_MACRO(...) SomeFunction(true PW_COMMA_ARGS(__VA_ARGS__))
-//
-// both MY_MACRO(1, 2) and MY_MACRO(1, 2, ) expand to SomeFunction(true, 1, 2).
-//
-// These macros were generated using the following Python code:
-//
-// for i in range(2, 33):
-// args = ', '.join(f'a{arg}' for arg in range(1, i))
-// print(f'#define _PW_COMMA_ARGS_{i}({args}, a{i}) '
-// f', {args} _PW_COMMA_ARGS_1(a{i})')
-//
-// clang-format off
-#define _PW_COMMA_ARGS_2(a1, a2) , a1 _PW_COMMA_ARGS_1(a2)
-#define _PW_COMMA_ARGS_3(a1, a2, a3) , a1, a2 _PW_COMMA_ARGS_1(a3)
-#define _PW_COMMA_ARGS_4(a1, a2, a3, a4) , a1, a2, a3 _PW_COMMA_ARGS_1(a4)
-#define _PW_COMMA_ARGS_5(a1, a2, a3, a4, a5) , a1, a2, a3, a4 _PW_COMMA_ARGS_1(a5)
-#define _PW_COMMA_ARGS_6(a1, a2, a3, a4, a5, a6) , a1, a2, a3, a4, a5 _PW_COMMA_ARGS_1(a6)
-#define _PW_COMMA_ARGS_7(a1, a2, a3, a4, a5, a6, a7) , a1, a2, a3, a4, a5, a6 _PW_COMMA_ARGS_1(a7)
-#define _PW_COMMA_ARGS_8(a1, a2, a3, a4, a5, a6, a7, a8) , a1, a2, a3, a4, a5, a6, a7 _PW_COMMA_ARGS_1(a8)
-#define _PW_COMMA_ARGS_9(a1, a2, a3, a4, a5, a6, a7, a8, a9) , a1, a2, a3, a4, a5, a6, a7, a8 _PW_COMMA_ARGS_1(a9)
-#define _PW_COMMA_ARGS_10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) , a1, a2, a3, a4, a5, a6, a7, a8, a9 _PW_COMMA_ARGS_1(a10)
-#define _PW_COMMA_ARGS_11(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) , a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 _PW_COMMA_ARGS_1(a11)
-#define _PW_COMMA_ARGS_12(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) , a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11 _PW_COMMA_ARGS_1(a12)
-#define _PW_COMMA_ARGS_13(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) , a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 _PW_COMMA_ARGS_1(a13)
-#define _PW_COMMA_ARGS_14(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) , a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13 _PW_COMMA_ARGS_1(a14)
-#define _PW_COMMA_ARGS_15(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) , a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14 _PW_COMMA_ARGS_1(a15)
-#define _PW_COMMA_ARGS_16(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) , a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 _PW_COMMA_ARGS_1(a16)
-#define _PW_COMMA_ARGS_17(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) , a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16 _PW_COMMA_ARGS_1(a17)
-#define _PW_COMMA_ARGS_18(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) , a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17 _PW_COMMA_ARGS_1(a18)
-#define _PW_COMMA_ARGS_19(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) , a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18 _PW_COMMA_ARGS_1(a19)
-#define _PW_COMMA_ARGS_20(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) , a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19 _PW_COMMA_ARGS_1(a20)
-#define _PW_COMMA_ARGS_21(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21) , a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20 _PW_COMMA_ARGS_1(a21)
-#define _PW_COMMA_ARGS_22(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22) , a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21 _PW_COMMA_ARGS_1(a22)
-#define _PW_COMMA_ARGS_23(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23) , a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22 _PW_COMMA_ARGS_1(a23)
-#define _PW_COMMA_ARGS_24(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24) , a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23 _PW_COMMA_ARGS_1(a24)
-#define _PW_COMMA_ARGS_25(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25) , a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24 _PW_COMMA_ARGS_1(a25)
-#define _PW_COMMA_ARGS_26(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26) , a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25 _PW_COMMA_ARGS_1(a26)
-#define _PW_COMMA_ARGS_27(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27) , a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26 _PW_COMMA_ARGS_1(a27)
-#define _PW_COMMA_ARGS_28(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28) , a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27 _PW_COMMA_ARGS_1(a28)
-#define _PW_COMMA_ARGS_29(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29) , a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28 _PW_COMMA_ARGS_1(a29)
-#define _PW_COMMA_ARGS_30(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30) , a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29 _PW_COMMA_ARGS_1(a30)
-#define _PW_COMMA_ARGS_31(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31) , a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30 _PW_COMMA_ARGS_1(a31)
-#define _PW_COMMA_ARGS_32(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32) , a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31 _PW_COMMA_ARGS_1(a32)
-// clang-format on
-
-#define _PW_COMMA_ARGS_0()
-
-// If there is one argument, make a comma only if the argument is not empty.
-#define _PW_COMMA_ARGS_1(arg) _PW_SKIP_COMMA(PW_EMPTY_ARGS(arg)) arg
-
-#define _PW_SKIP_COMMA(no_comma) _PW_SKIP_COMMA_X(no_comma)
-#define _PW_SKIP_COMMA_X(no_comma) _PW_SKIP_COMMA_##no_comma
-#define _PW_SKIP_COMMA_1
-#define _PW_SKIP_COMMA_0 ,
+#define _PW_COMMA_ARGS(...) , __VA_ARGS__
// Allows calling a different function-like macro based on the number of
// arguments. For example:
@@ -209,8 +186,9 @@
// ARG_PRINT("a", "b"); // Outputs: 2 arg: a, b
// ARG_PRINT("a", "b", "c"); // Outputs: 3 arg: a, b, c
//
-#define PW_DELEGATE_BY_ARG_COUNT(func, ...) \
- _PW_DELEGATE_BY_ARG_COUNT(func, PW_ARG_COUNT(__VA_ARGS__))(__VA_ARGS__)
-#define _PW_DELEGATE_BY_ARG_COUNT_EXPANDED(name, n) name##n
-#define _PW_DELEGATE_BY_ARG_COUNT(name, n) \
- _PW_DELEGATE_BY_ARG_COUNT_EXPANDED(name, n)
+#define PW_DELEGATE_BY_ARG_COUNT(function, ...) \
+ _PW_DELEGATE_BY_ARG_COUNT( \
+ _PW_PASTE2(function, PW_FUNCTION_ARG_COUNT(__VA_ARGS__)), \
+ PW_DROP_LAST_ARG_IF_EMPTY(__VA_ARGS__))
+
+#define _PW_DELEGATE_BY_ARG_COUNT(function, ...) function(__VA_ARGS__)