Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Must a "is defined" macro check and its call be in separate conditions?

I was struggling to find an answer amoung many that refer to this topic on SO, but here's some seemingly innocent looking code that fails to compile when F is not a defined macro,

int main() {
#if defined(F) && F(0, 2, 0)
  return 0;
#endif
  return 1;
}

The problem, according to this section of the GCC manual is that inside #if expressions "all macros in the expression are expanded before actual computation of the expression’s value begins", so this in an invalid check, since when F is undefined, I see,

test.cpp:2:20: error: missing binary operator before token "("
 #if defined(F) && F(0, 2, 0)
                    ^

My question: is the only way to correctly do this check like so?

int main() {
#if defined(F)
#if F(0, 2, 0)
  return 0;
#endif
#endif
  return 1;
}

I find this quite ugly and unintuitive, so I'm hoping there's a nicer way to do such things in the preprocessor.

like image 279
Charles Avatar asked Nov 07 '22 04:11

Charles


1 Answers

Assuming your F macro is defined in some header file, you could place the following code somewhere between the include and its first usage:

#ifndef F
#define F(a,b,c) 0
#endif

Or another reasonable default. That's a common solution for your problem. Another is to not allow such macros to be not defined, but require either the default value or whatever it's expected to do. This latter approach is a bit safer for e.g. configuration files, as it makes clear the author did consider the macro and intentionally picked a value (i.e. he did not just forget to define it). It's also easier if the definition is in the same file.

Your test would then just be:

#if F(0, 2, 0)

Avoiding the nested condition (which would cause additional trouble if there was an #else required somewhere.

Two words of advise:

  • Use macros carefully and sparesely, only when reasonble. Expecially C++ provides features which reduce the need for macros.
  • Don't use single-letter names for macros. Remember they are textual replacements, bejond the normal language syntax. Use self-explanatory names instead (this does not only apply to macros, but for those it's even more relevant).
like image 171
too honest for this site Avatar answered Nov 10 '22 00:11

too honest for this site