-1

The following structure for C preprocessor directive #if works well.

#define C  1

#if C==1
...
#endif

But I'd like to use something like this:

#define REAL double

#if REAL==double
...
#elif REAL==float
...
#else
   assert(0);
#endif

It's not valid. Is there a solution?

Krishna Kanth Yenumula
  • 2,533
  • 2
  • 14
  • 26
apadana
  • 574
  • 2
  • 19
  • 3
    This answer may help: https://stackoverflow.com/questions/2335888/how-to-compare-strings-in-c-conditional-preprocessor-directives – Outrageous Bacon Nov 14 '20 at 00:10
  • 2
    `Is there a solution?` Solution to? This seems for me to be XY question - you are using `#if` to choose some type related code - what is the real problem you are trying to solve? Why not just write `REAL a = 1` and forget about it? – KamilCuk Nov 14 '20 at 00:24
  • @KamilCuk, I wanted to declare real variables in the code like this: `REAL r1, r2;` I found another way. – apadana Nov 14 '20 at 00:30
  • 1
    `REAL r1, r2;` so just do it, it should work with the code you've shown.. Anyway, why not `typedef`? `typedef double REAL` would be as good. `I found another way.` then should this question be closed? – KamilCuk Nov 14 '20 at 00:40
  • @KamilCuk, I wanted `roundf()` be used instead of `round()` and so on when `REAL` was defined as `float`, and vice versa. First, I was going to use `#if`. Now I find `#ifdef` a better option. Anyway I hope that other people can learn from answer(s) to this question. – apadana Nov 14 '20 at 00:47
  • 2
    No need - just include [`tgmath.h`](https://en.cppreference.com/w/c/numeric/tgmath) in this case. And still would be cleaner to create a common abstraction/interface to the `REAL` type and use a single code flow, instead of multiple code flows. – KamilCuk Nov 14 '20 at 00:48
  • @KamilCuk, I wasn't familiar with that. Thanks. :) – apadana Nov 14 '20 at 00:51
  • If you want to use different code depending on the type of something, that's what the `_Generic` keyword was created for. – Christian Gibbons Nov 16 '20 at 17:39

1 Answers1

1

Is there a solution?

There is a whole world of ways you can combine macro expansion with conditional compilation. It's unclear which of them you would consider a solution, but here's a possibility:

#define doubledouble 1
#define floatfloat 1

#define concat_literal(x,y) x ## y
#define realtype(t1,t2) concat_literal(t1,t2)

// ...

#define REAL float

#if realtype(REAL, double)
    // REAL is double
#elif realtype(REAL, float)
    // REAL is float
#else
    // REAL is something else
#endif

The realtype macro works by macro-expanding its arguments and concatenating them together. On rescan, if the result is doubledouble or floatfloat then that is expanded further to 1. If it is an identifier that is not defined as a macro name, then the #if treats it as 0.

It's not foolproof, of course. It does not work if REAL has a multi-token expansion, such as long double. There's also a minor risk of collision with other defined macro names.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157