1

I want to define a macro like this

#define ASSERT_EXIST(error, ...)  some-impl-here

then we can call it like this

ASSERT_EXIST(100, a, b, c)

and it should be expand to this

if (!a_exists)  return error("a is missing", 100);
if (!b_exists)  return error("b is missing", 100);
if (!c_exists)  return error("c is missing", 100);

the most trouble part of this is I can't iterate over __VA_ARGS__ easily in a macro.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
zhihuifan
  • 1,093
  • 2
  • 16
  • 30
  • You need to have a limit on the number of variables that you can pass to the `ASSERT_EXIST` macro. AFAIK, there is no way to write a macro that can expand all the arguments passed to it. – Ajay Brahmakshatriya Jun 12 '19 at 02:23
  • Look at the [Boost Preprocessor](https://www.boost.org/doc/libs/1_70_0/libs/preprocessor/doc/index.html) library (nominally for C++, but perfectly usable with C too). It has tools to handle those requirements, at least for sensible sizes of argument list. If you insist on 300 arguments, you may have some extra work to do. See also [Macro returning the numnber of arguments it is given in C](https://stackoverflow.com/questions/2308243/macro-returning-the-number-of-arguments-it-is-given-in-c) and related questions. – Jonathan Leffler Jun 12 '19 at 02:31

2 Answers2

1

There are various dirty tricks where you can have variadic macros work up to a certain fixed number. However, the proper and correct solution is to not write a variadic macro at all. It is much better practice to simply use

#define ASSERT_EXISTS(val, x) if (!x##_exists) { return error(#x " is missing", val); }

ASSERT_EXIST(100, a);
ASSERT_EXIST(100, b);
...

Or better yet, drop all such icky macros in favour of readable standard C.

if(!a_exists) { return error("a is missing", 100); }
if(!b_exists) { return error("b is missing", 100); }
if(!c_exists) { return error("c is missing", 100); }

Sure, code repetition is bad practice, but secret macro languages are extremely bad practice.

Lundin
  • 195,001
  • 40
  • 254
  • 396
-1

If you just want to throw variable number of arguments to a function, __VA_ARGS__ is enough as you already did. To handle the trending comma, sometimes you may also need ##.

If you want to iterate through the arguments, use varargs from <stdarg.h>.

stdarg.h

Galaxy
  • 1,129
  • 11
  • 27