Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a boolean indicating if a macro is defined or not?

My code is configurable with define macros. To get the value in the code, I'm doing this:

#ifdef CONFIG_X
static constexpr bool x = true;
#else
static constexpr bool x = false;
#endif

But this is quickly becoming very ugly in the code with several configuration variables...

Another solution I found is simply to cut the code in two:

#ifdef CONFIG_X
#define CONFIG_X_BOOL true
#else
#define CONFIG_X_BOOL false
#endif

static constexpr bool x = CONFIG_X_BOOL;

This is a bit better, but not really nice either.

Is there a nice way to have a boolean or a 1 or 0 if a macro is defined ?

like image 769
Baptiste Wicht Avatar asked Dec 21 '16 15:12

Baptiste Wicht


People also ask

How do I know if a macro is defined?

To check – A Macro is defined or not, we use #ifdef preprocessor directive. To check whether a Macro is defined or not in C language – we use #ifdef preprocessor directive, it is used to check Macros only. If MACRO_NAME is defined, then the compiler will compile //body (a set of statements written within the #ifdef ...

Is Boolean a macro?

In C, bool is a macro. There is no built-in type or keyword by the name of bool in C, so typical implementations use the standard library to #define true and false to 1 and 0 respectively.

How is bool defined in C++?

Simply put, a Boolean variable can only have two possible values: true or false. In C++, we use the keyword bool to declare this kind of variable. Let's take a look at an example: bool b1 = true; bool b2 = false; In C++, Boolean values declared true are assigned the value of 1, and false values are assigned 0.

Is bool a keyword?

bool is a keyword that is used to declare a variable which can store Boolean values true or false.


1 Answers

This IS possible, but only in the limited case where you are looking for empty defines (as is often the case with compilation flags) or where you know the range of ways a flag will be defined, such as with a 0 or 1.

Here is working code:

#include <iostream>

// Define two genetic macros
#define SECOND_ARG(A,B,...) B
#define CONCAT2(A,B) A ## B

// If a macro is detected, add an arg, so the second one will be 1.
#define DETECT_EXIST_TRUE ~,1

// DETECT_EXIST merely concats a converted macro to the end of DETECT_EXIST_TRUE.
// If empty, DETECT_EXIST_TRUE converts fine.  If not 0 remains second argument.
#define DETECT_EXIST(X) DETECT_EXIST_IMPL(CONCAT2(DETECT_EXIST_TRUE,X), 0, ~)
#define DETECT_EXIST_IMPL(...) SECOND_ARG(__VA_ARGS__)

// We will create MY_DEFINE, but not MY_DEFINE2
#define MY_DEFINE

int main()
{
  // We can now use DETECT_EXIST to detect defines.
  std::cout << "MY_DEFINE = " << DETECT_EXIST(MY_DEFINE) << std::endl;
  std::cout << "MY_DEFINE2 = " << DETECT_EXIST(MY_DEFINE2) << std::endl;
}

This code will produce the output:

MY_DEFINE = 1
MY_DEFINE2 = 0

Since the first one does exist and the second doesn't.

If the macro is set to a value such as 1, you just need to have an alternate version of DETECT_EXIST_TRUE to handle it, with the macro value pasted on the end. For example:

#define DETECT_EXIST_TRUE1 ~,1

Then if you have:

#define MY_DEFINE1 1

Code like this will also work correctly in main:

std::cout << "MY_DEFINE1 = " << DETECT_EXIST(MY_DEFINE1) << std::endl;
like image 148
Charles Ofria Avatar answered Sep 17 '22 14:09

Charles Ofria