pw_preprocessor: Rename macro; reorganize header
- Rename PW_ARG_COUNT to PW_MACRO_ARG_COUNT.
- Reorganize the arguments.h header to put the high-level, easier-to-use
macros first (PW_DELEGATE_BY_ARG_COUNT and PW_COMMA_ARGS).
- Fix the test that demonstrates what happens when PW_COMMA_ARGS is
used incorrectly.
- Update the documentation for arguments.h.
Change-Id: I741995c02e1f36ca805f4ba15eb113caa98164f8
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/17501
Commit-Queue: Wyatt Hepler <hepler@google.com>
Reviewed-by: Keir Mierle <keir@google.com>
diff --git a/pw_preprocessor/arguments_test.cc b/pw_preprocessor/arguments_test.cc
index 2ca76c5..4196298 100644
--- a/pw_preprocessor/arguments_test.cc
+++ b/pw_preprocessor/arguments_test.cc
@@ -11,12 +11,14 @@
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
-//
-// All of these tests are static asserts. If the test compiles, it has already
-// passed. The TEST functions are used for organization only.
+
+// Many of these tests are static asserts. If these compile, they pass. The TEST
+// functions are used for organization only.
#include "pw_preprocessor/arguments.h"
+#include <tuple>
+
#include "pw_unit_test/framework.h"
namespace pw {
@@ -126,45 +128,38 @@
#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__))
+ _BAD_DEMO_CAPTURE_ARGS("%d: " fmt, 123 PW_COMMA_ARGS(__VA_ARGS__))
-#define _BAD_DEMO_STRINGIFY(...) PW_STRINGIFY(__VA_ARGS__)
+#define _BAD_DEMO_CAPTURE_ARGS(...) std::make_tuple(__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
+TEST(CommaVarargs, MisbehavesWithMacroToMacroUse_NoArgs_ArgsAreOkay) {
+ auto [a1, a2] = BAD_DEMO("Hello world");
+ EXPECT_STREQ(a1, "%d: Hello world");
+ EXPECT_EQ(a2, 123);
+}
+TEST(CommaVarargs, MisbehavesWithMacroToMacroUse_WithArgs_ArgsOutOfOrder) {
// 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)");
+ const auto [a1, a2, a3] = BAD_DEMO("Hello %s", "world?");
+ EXPECT_STREQ(a1, "%d: Hello %s");
+ EXPECT_STREQ(a2, "world?");
+ EXPECT_EQ(a3, 123);
}
TEST(CountArgs, Zero) {
- static_assert(PW_ARG_COUNT() == 0);
- static_assert(PW_ARG_COUNT(/**/) == 0);
- static_assert(PW_ARG_COUNT(/* uhm, hi */) == 0);
+ static_assert(PW_MACRO_ARG_COUNT() == 0);
+ static_assert(PW_MACRO_ARG_COUNT(/**/) == 0);
+ static_assert(PW_MACRO_ARG_COUNT(/* uhm, hi */) == 0);
// clang-format off
- static_assert(PW_ARG_COUNT( ) == 0);
- static_assert(PW_ARG_COUNT(
+ static_assert(PW_MACRO_ARG_COUNT( ) == 0);
+ static_assert(PW_MACRO_ARG_COUNT(
) == 0);
- static_assert(PW_ARG_COUNT(
+ static_assert(PW_MACRO_ARG_COUNT(
// wow
// This is a comment.
) == 0);
@@ -173,23 +168,23 @@
TEST(CountArgs, Commas) {
// clang-format off
- static_assert(PW_ARG_COUNT(,) == 2);
- static_assert(PW_ARG_COUNT(,,) == 3);
- static_assert(PW_ARG_COUNT(,,,) == 4);
+ static_assert(PW_MACRO_ARG_COUNT(,) == 2);
+ static_assert(PW_MACRO_ARG_COUNT(,,) == 3);
+ static_assert(PW_MACRO_ARG_COUNT(,,,) == 4);
// clang-format on
- static_assert(PW_ARG_COUNT(, ) == 2);
- static_assert(PW_ARG_COUNT(, , ) == 3);
- static_assert(PW_ARG_COUNT(, , , ) == 4);
+ static_assert(PW_MACRO_ARG_COUNT(, ) == 2);
+ static_assert(PW_MACRO_ARG_COUNT(, , ) == 3);
+ static_assert(PW_MACRO_ARG_COUNT(, , , ) == 4);
}
TEST(CountArgs, Parentheses) {
- static_assert(PW_ARG_COUNT(()) == 1);
- static_assert(PW_ARG_COUNT((1, 2, 3, 4)) == 1);
- 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);
- static_assert(PW_ARG_COUNT(1, (2, 3, 4), (<5, 6>)) == 3);
+ static_assert(PW_MACRO_ARG_COUNT(()) == 1);
+ static_assert(PW_MACRO_ARG_COUNT((1, 2, 3, 4)) == 1);
+ static_assert(PW_MACRO_ARG_COUNT((1, 2, 3), (1, 2, 3, 4)) == 2);
+ static_assert(PW_MACRO_ARG_COUNT((), ()) == 2);
+ static_assert(PW_MACRO_ARG_COUNT((-), (o)) == 2);
+ static_assert(PW_MACRO_ARG_COUNT((, , (, , ), ), (123, 4)) == 2);
+ static_assert(PW_MACRO_ARG_COUNT(1, (2, 3, 4), (<5, 6>)) == 3);
}
template <typename... Args>
@@ -260,7 +255,7 @@
static_assert(FunctionArgCount(PW_DROP_LAST_ARG_IF_EMPTY(1, 2, 3, )) == 3);
}
-#define SOME_VARIADIC_MACRO(...) PW_ARG_COUNT(__VA_ARGS__)
+#define SOME_VARIADIC_MACRO(...) PW_MACRO_ARG_COUNT(__VA_ARGS__)
#define ANOTHER_VARIADIC_MACRO(arg, ...) SOME_VARIADIC_MACRO(__VA_ARGS__)
@@ -295,75 +290,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}) ')
+ print(f' static_assert(PW_MACRO_ARG_COUNT({", ".join(args)}) == {i}) ')
*/
TEST(CountArgs, AllSupported) {
// clang-format off
- 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);
+ static_assert(PW_MACRO_ARG_COUNT() == 0);
+ static_assert(PW_MACRO_ARG_COUNT(X1) == 1);
+ static_assert(PW_MACRO_ARG_COUNT(X1, X2) == 2);
+ static_assert(PW_MACRO_ARG_COUNT(X1, X2, X3) == 3);
+ static_assert(PW_MACRO_ARG_COUNT(X1, X2, X3, X4) == 4);
+ static_assert(PW_MACRO_ARG_COUNT(X1, X2, X3, X4, X5) == 5);
+ static_assert(PW_MACRO_ARG_COUNT(X1, X2, X3, X4, X5, X6) == 6);
+ static_assert(PW_MACRO_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7) == 7);
+ static_assert(PW_MACRO_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8) == 8);
+ static_assert(PW_MACRO_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9) == 9);
+ static_assert(PW_MACRO_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10) == 10);
+ static_assert(PW_MACRO_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11) == 11);
+ static_assert(PW_MACRO_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12) == 12);
+ static_assert(PW_MACRO_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13) == 13);
+ static_assert(PW_MACRO_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14) == 14);
+ static_assert(PW_MACRO_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15) == 15);
+ static_assert(PW_MACRO_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16) == 16);
+ static_assert(PW_MACRO_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17) == 17);
+ static_assert(PW_MACRO_ARG_COUNT(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18) == 18);
+ static_assert(PW_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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_MACRO_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/docs.rst b/pw_preprocessor/docs.rst
index ae08b13..74345f1 100644
--- a/pw_preprocessor/docs.rst
+++ b/pw_preprocessor/docs.rst
@@ -17,6 +17,51 @@
=======
The preprocessor module provides several headers.
+pw_preprocessor/arguments.h
+---------------------------------
+Defines macros for handling variadic arguments to function-like macros. Macros
+include the following:
+
+.. c:function:: PW_DELEGATE_BY_ARG_COUNT(name, ...)
+
+ Selects and invokes a macro based on the number of arguments provided. Expands
+ to ``<name><arg_count>(...)``. For example,
+ ``PW_DELEGATE_BY_ARG_COUNT(foo_, 1, 2, 3)`` expands to ``foo_3(1, 2, 3)``.
+
+ This example shows how ``PW_DELEGATE_BY_ARG_COUNT`` could be used to log a
+ customized message based on the number of arguments provided.
+
+ .. code-block:: cpp
+
+ #define ARG_PRINT(...) PW_DELEGATE_BY_ARG_COUNT(_ARG_PRINT, __VA_ARGS__)
+ #define _ARG_PRINT_0(a) LOG_INFO("nothing!")
+ #define _ARG_PRINT_1(a) LOG_INFO("1 arg: %s", a)
+ #define _ARG_PRINT_2(a, b) LOG_INFO("2 args: %s, %s", a, b)
+ #define _ARG_PRINT_3(a, b, c) LOG_INFO("3 args: %s, %s, %s", a, b, c)
+
+ When used, ``ARG_PRINT`` expands to the ``_ARG_PRINT_#`` macro corresponding
+ to the number of arguments.
+
+ .. code-block:: cpp
+
+ ARG_PRINT(); // Outputs: nothing!
+ ARG_PRINT("a"); // Outputs: 1 arg: a
+ ARG_PRINT("a", "b"); // Outputs: 2 args: a, b
+ ARG_PRINT("a", "b", "c"); // Outputs: 3 args: a, b, c
+
+.. c:function:: PW_COMMA_ARGS(...)
+
+ Expands to a comma followed by the arguments if any arguments are provided.
+ Otherwise, expands to nothing. If the final argument is empty, it is omitted.
+ This is useful when passing ``__VA_ARGS__`` to a variadic function or template
+ parameter list, since it removes the extra comma when no arguments are
+ provided. ``PW_COMMA_ARGS`` must NOT be used when invoking a macro from
+ another macro.
+
+ For example. ``PW_COMMA_ARGS(1, 2, 3)``, expands to ``, 1, 2, 3``, while
+ ``PW_COMMA_ARGS()`` expands to nothing. ``PW_COMMA_ARGS(1, 2, )`` expands to
+ ``, 1, 2``.
+
pw_preprocessor/boolean.h
-------------------------
Defines macros for boolean logic on literal 1s and 0s. This is useful for
@@ -32,19 +77,6 @@
macros and token pastes the results. This can be used for building names of
classes, variables, macros, etc.
-pw_preprocessor/macro_arg_count.h
----------------------------------
-Defines the ``PW_ARG_COUNT(...)`` macro, which counts the number of arguments it
-was passed. It can be invoked directly or with ``__VA_ARGS__`` in another macro.
-``PW_ARG_COUNT(...)`` evaluates to a literal of the number of arguments which
-can be used directly or concatenated to build other names. Unlike many common
-implementations, this macro correctly evaluates to ``0`` when it is invoked
-without arguments.
-
-This header also defines ``PW_HAS_ARGS(...)`` and ``PW_HAS_NO_ARGS(...)``,
-which evaluate to ``1`` or ``0`` depending on whether they are invoked with
-arguments.
-
pw_preprocessor/util.h
----------------------
General purpose, useful macros.
diff --git a/pw_preprocessor/public/pw_preprocessor/arguments.h b/pw_preprocessor/public/pw_preprocessor/arguments.h
index 2d9a51f..bb7e80b 100644
--- a/pw_preprocessor/public/pw_preprocessor/arguments.h
+++ b/pw_preprocessor/public/pw_preprocessor/arguments.h
@@ -11,128 +11,13 @@
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
-//
-// Macros for counting the number of arguments passed to a variadic
-// function-like macro.
+
+// Macros for working with arguments to function-like macros.
#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
-// is not currently supported.
-//
-// PW_ARG_COUNT is most commonly used to count __VA_ARGS__ in a variadic macro.
-// For example, the following code counts the number of arguments passed to a
-// logging macro:
-//
-/* #define LOG_INFO(format, ...) { \
- static const int kArgCount = PW_ARG_COUNT(__VA_ARGS__); \
- SendLog(kArgCount, format, ##__VA_ARGS__); \
- }
-*/
-// clang-format off
-#define PW_ARG_COUNT(...) \
- _PW_ARG_COUNT_IMPL(__VA_ARGS__, \
- 64, 63, 62, 61, 60, 59, 58, 57, \
- 56, 55, 54, 53, 52, 51, 50, 49, \
- 48, 47, 46, 45, 44, 43, 42, 41, \
- 40, 39, 38, 37, 36, 35, 34, 33, \
- 32, 31, 30, 29, 28, 27, 26, 25, \
- 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__))
-
-// Expands to 0 if one or more arguments are provided, 1 otherwise. This
-// approach is from Jens Gustedt's blog:
-// https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/
-//
-// Normally, with a standard-compliant C preprocessor, it's impossible to tell
-// whether a variadic macro was called with no arguments or with one argument.
-// A macro invoked with no arguments is actually passed one empty argument.
-//
-// This macro works by checking for the presence of a comma in four situations.
-// These situations give the following information about __VA_ARGS__:
-//
-// 1. It is two or more variadic arguments.
-// 2. It expands to one argument surrounded by parentheses.
-// 3. It is a function-like macro that produces a comma when invoked.
-// 4. It does not interfere with calling a macro when placed between it and
-// parentheses.
-//
-// If a comma is not present in 1, 2, 3, but is present in 4, then __VA_ARGS__
-// is empty. For this case (0001), and only this case, a corresponding macro
-// that expands to a comma is defined. The presence of this comma determines
-// whether any arguments were passed in.
-//
-// C++20 introduces __VA_OPT__, which would greatly simplify this macro.
-#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, \
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
-
-#define _PW_ARG_COUNT_IMPL(a64, a63, a62, a61, a60, a59, a58, a57, \
- a56, a55, a54, a53, a52, a51, a50, a49, \
- a48, a47, a46, a45, a44, a43, a42, a41, \
- a40, a39, a38, a37, a36, a35, a34, a33, \
- a32, a31, a30, a29, a28, a27, a26, a25, \
- a24, a23, a22, a21, a20, a19, a18, a17, \
- a16, a15, a14, a13, a12, a11, a10, a09, \
- a08, a07, a06, a05, a04, a03, a02, a01, \
- count, ...) \
- 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
-#define _PW_HAS_COMMA_CASE_0001 ,
-#define _PW_MAKE_COMMA_IF_CALLED(...) ,
-
// Expands to a comma followed by __VA_ARGS__, if __VA_ARGS__ is non-empty.
// Otherwise, expands to nothing. If the final argument is empty, it is omitted.
// This is useful when passing __VA_ARGS__ to a variadic function or template
@@ -173,18 +58,19 @@
#define _PW_COMMA_ARGS(...) , __VA_ARGS__
-// Allows calling a different function-like macro based on the number of
-// arguments. For example:
+// Allows calling a different function-like macros based on the number of
+// arguments. For example:
//
// #define ARG_PRINT(...) PW_DELEGATE_BY_ARG_COUNT(_ARG_PRINT, __VA_ARGS__)
// #define _ARG_PRINT1(a) LOG_INFO("1 arg: %s", a)
// #define _ARG_PRINT2(a, b) LOG_INFO("2 args: %s, %s", a, b)
// #define _ARG_PRINT3(a, b, c) LOG_INFO("3 args: %s, %s, %s", a, b, c)
//
-// This can the be called in code:
+// This can the be called from C/C++ code:
+//
// ARG_PRINT("a"); // Outputs: 1 arg: a
-// ARG_PRINT("a", "b"); // Outputs: 2 arg: a, b
-// ARG_PRINT("a", "b", "c"); // Outputs: 3 arg: a, b, c
+// ARG_PRINT("a", "b"); // Outputs: 2 args: a, b
+// ARG_PRINT("a", "b", "c"); // Outputs: 3 args: a, b, c
//
#define PW_DELEGATE_BY_ARG_COUNT(function, ...) \
_PW_DELEGATE_BY_ARG_COUNT( \
@@ -192,3 +78,117 @@
PW_DROP_LAST_ARG_IF_EMPTY(__VA_ARGS__))
#define _PW_DELEGATE_BY_ARG_COUNT(function, ...) function(__VA_ARGS__)
+
+// PW_MACRO_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 is not currently supported.
+//
+// PW_MACRO_ARG_COUNT is most commonly used to count __VA_ARGS__ in a variadic
+// macro. For example, the following code counts the number of arguments passed
+// to a logging macro:
+//
+/* #define LOG_INFO(format, ...) { \
+ static const int kArgCount = PW_MACRO_ARG_COUNT(__VA_ARGS__); \
+ SendLog(kArgCount, format, ##__VA_ARGS__); \
+ }
+*/
+// clang-format off
+#define PW_MACRO_ARG_COUNT(...) \
+ _PW_MACRO_ARG_COUNT_IMPL(__VA_ARGS__, \
+ 64, 63, 62, 61, 60, 59, 58, 57, \
+ 56, 55, 54, 53, 52, 51, 50, 49, \
+ 48, 47, 46, 45, 44, 43, 42, 41, \
+ 40, 39, 38, 37, 36, 35, 34, 33, \
+ 32, 31, 30, 29, 28, 27, 26, 25, \
+ 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_MACRO_ARG_COUNT
+#define _PW_FUNCTION_ARG_COUNT_1(...) \
+ PW_MACRO_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_MACRO_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_MACRO_ARG_COUNT(__VA_ARGS__))(__VA_ARGS__)
+
+// Evaluates to the arguments, excluding the final argument if it is empty.
+#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__))
+
+// Expands to 0 if one or more arguments are provided, 1 otherwise. This
+// approach is from Jens Gustedt's blog:
+// https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/
+//
+// Normally, with a standard-compliant C preprocessor, it's impossible to tell
+// whether a variadic macro was called with no arguments or with one argument.
+// A macro invoked with no arguments is actually passed one empty argument.
+//
+// This macro works by checking for the presence of a comma in four situations.
+// These situations give the following information about __VA_ARGS__:
+//
+// 1. It is two or more variadic arguments.
+// 2. It expands to one argument surrounded by parentheses.
+// 3. It is a function-like macro that produces a comma when invoked.
+// 4. It does not interfere with calling a macro when placed between it and
+// parentheses.
+//
+// If a comma is not present in 1, 2, 3, but is present in 4, then __VA_ARGS__
+// is empty. For this case (0001), and only this case, a corresponding macro
+// that expands to a comma is defined. The presence of this comma determines
+// whether any arguments were passed in.
+//
+// C++20 introduces __VA_OPT__, which would greatly simplify this macro.
+#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_MACRO_ARG_COUNT_IMPL(__VA_ARGS__, \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
+
+#define _PW_MACRO_ARG_COUNT_IMPL(a64, a63, a62, a61, a60, a59, a58, a57, \
+ a56, a55, a54, a53, a52, a51, a50, a49, \
+ a48, a47, a46, a45, a44, a43, a42, a41, \
+ a40, a39, a38, a37, a36, a35, a34, a33, \
+ a32, a31, a30, a29, a28, a27, a26, a25, \
+ a24, a23, a22, a21, a20, a19, a18, a17, \
+ a16, a15, a14, a13, a12, a11, a10, a09, \
+ a08, a07, a06, a05, a04, a03, a02, a01, \
+ count, ...) \
+ 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
+#define _PW_HAS_COMMA_CASE_0001 ,
+#define _PW_MAKE_COMMA_IF_CALLED(...) ,
diff --git a/pw_preprocessor/public/pw_preprocessor/concat.h b/pw_preprocessor/public/pw_preprocessor/concat.h
index e8045e1..0d9bc11 100644
--- a/pw_preprocessor/public/pw_preprocessor/concat.h
+++ b/pw_preprocessor/public/pw_preprocessor/concat.h
@@ -18,10 +18,11 @@
// Expands macros and concatenates the results using preprocessor ##
// concatentation. Supports up to 32 arguments.
-#define PW_CONCAT(...) _PW_CONCAT_IMPL1(PW_ARG_COUNT(__VA_ARGS__), __VA_ARGS__)
+#define PW_CONCAT(...) \
+ _PW_CONCAT_IMPL1(PW_MACRO_ARG_COUNT(__VA_ARGS__), __VA_ARGS__)
-// Expand the macro to allow PW_ARG_COUNT and any caller-provided macros to be
-// evaluated before concatenating the tokens.
+// Expand the macro to allow PW_MACRO_ARG_COUNT and any caller-provided macros
+// to be evaluated before concatenating the tokens.
#define _PW_CONCAT_IMPL1(count, ...) _PW_CONCAT_IMPL2(count, __VA_ARGS__)
#define _PW_CONCAT_IMPL2(count, ...) _PW_CONCAT_##count(__VA_ARGS__)
diff --git a/pw_tokenizer/argument_types_test.cc b/pw_tokenizer/argument_types_test.cc
index a4d2676..67c1d17 100644
--- a/pw_tokenizer/argument_types_test.cc
+++ b/pw_tokenizer/argument_types_test.cc
@@ -75,7 +75,7 @@
// uint64_t).
#define PACKED_TYPES(...) \
((PW_CONCAT(0b, __VA_ARGS__, u) << PW_TOKENIZER_TYPE_COUNT_SIZE_BITS) | \
- PW_ARG_COUNT(__VA_ARGS__))
+ PW_MACRO_ARG_COUNT(__VA_ARGS__))
// Test this test macro for both uint32_t and uint64_t.
#if PW_TOKENIZER_CFG_ARG_TYPES_SIZE_BYTES == 4
diff --git a/pw_tokenizer/public/pw_tokenizer/tokenize.h b/pw_tokenizer/public/pw_tokenizer/tokenize.h
index 3c36950..fd776b4 100644
--- a/pw_tokenizer/public/pw_tokenizer/tokenize.h
+++ b/pw_tokenizer/public/pw_tokenizer/tokenize.h
@@ -190,11 +190,11 @@
\
/* Check that the macro is invoked with a supported number of arguments. */ \
static_assert( \
- PW_ARG_COUNT(__VA_ARGS__) <= PW_TOKENIZER_MAX_SUPPORTED_ARGS, \
+ PW_FUNCTION_ARG_COUNT(__VA_ARGS__) <= PW_TOKENIZER_MAX_SUPPORTED_ARGS, \
"Tokenized strings cannot have more than " \
PW_STRINGIFY(PW_TOKENIZER_MAX_SUPPORTED_ARGS) " arguments; " \
- PW_STRINGIFY(PW_ARG_COUNT(__VA_ARGS__)) " arguments were used for " \
- #format " (" #__VA_ARGS__ ")"); \
+ PW_STRINGIFY(PW_FUNCTION_ARG_COUNT(__VA_ARGS__)) \
+ " arguments were used for " #format " (" #__VA_ARGS__ ")"); \
\
/* Tokenize the string to a pw_tokenizer_Token at compile time. */ \
_PW_TOKENIZER_CONST pw_tokenizer_Token _pw_tokenizer_token = \