0

I want to essentially have a macro shortener.

The macro, FOO(A,B,C) should expand to defined(_FOO_A) || defined(_FOO_B) || defined(_FOO_C).

Is that possible in GCC using variadic macro arguments and not actually writing 3 functions (FOO(A), FOO(A,B), FOO(A,B,C)) ?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Arindam
  • 342
  • 1
  • 12
  • 3
    Identifiers that start with two underscores or with one underscore and a capital letter are reserved for use by the language implementation. – Carl Norum Dec 21 '12 at 22:31
  • Normally, I'd say write a loop that goes through the arguments and checks each defined... however, if defined is used in the context of a preprocessor directive, that's a no-go. – RonaldBarzell Dec 21 '12 at 22:34
  • The code you provided is an example of what you want in the general case or you need exactly that macro? – effeffe Dec 21 '12 at 23:13
  • @CarlNorum: I agree. I just provided it as an example and to distinguish between FOO and _FOO. – Arindam Dec 21 '12 at 23:34
  • @effeffe: I need that exact macro, with FOO substituted with another literal. – Arindam Dec 21 '12 at 23:36
  • Seems very similar to http://efesx.com/2010/08/31/overloading-macros/ and http://efesx.com/2010/07/17/variadic-macro-to-count-number-of-arguments/ You are most welcome to have a look. – rmn Dec 21 '12 at 22:32

2 Answers2

3

It is not possible to have a macro to expand to something that contains the defined keyword:

If the token defined is generated as a result of this replacement process or use of the defined unary operator does not match one of the two specified forms prior to macro replacement, the behavior is undefined.

So you can't do it with defined. If you are willing to relax that constraint by just testing the value of FOO_A_, FOO_B_, ... there are ways to do this by using P99. E.g just doing a logical or of a list of variables would be

#if P99_ORS(A, B, C)
...
#endif

where the P99_ORS expression expands to

((((A) || (B))) || (C))

and is then evaluated for #if the expression.

There would also be ways to expand that first into a token list of your liking, if you want to do some macro programming

#define P00_NAME_X(NAME, X, I) P99_PASTE2(NAME, X)
#define CONDITION(NAME, ...) P99_ORS(P99_FOR(FOO_, P99_NARG(__VA_ARGS__), P00_SEQ, P00_NAME_X, __VA_ARGS__))

such that

CONDITION(A, B, C, toto);

would expand to

((((((FOO_A) || (FOO_B))) || (FOO_C))) || (FOO_toto));
Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
2

Something like this?

#include <stdio.h>

#define FOO(A, B, C) (FOO_X(A) || FOO_X(B) || FOO_X(C))
#define FOO_X(x) defined(_FOO_##x)

// just to print it
#define QUOTE(...) QUOTE_AUX(__VA_ARGS__)
#define QUOTE_AUX(...) #__VA_ARGS__

int main(void)
{
    puts(QUOTE(FOO(a, b, c)));
}

EDIT: actually this results undefined behavior, in all C standards.

effeffe
  • 2,821
  • 3
  • 21
  • 44