C macro to enable and disable code features

2020-03-07 06:45发布

问题:

I've used a code base before that had a macro system for enabling and disabling sections of code. It looked something like the following:

#define IN_USE      X
#define NOT_IN_USE  _

#if defined( WIN32 )
    #define FEATURE_A       IN_USE
    #define FEATURE_B       IN_USE
    #define FEATURE_C       NOT_IN_USE
#elif defined( OSX )
    #define FEATURE_A       NOT_IN_USE
    #define FEATURE_B       NOT_IN_USE
    #define FEATURE_C       IN_USE
#else
    #define FEATURE_A       NOT_IN_USE
    #define FEATURE_B       NOT_IN_USE
    #define FEATURE_C       NOT_IN_USE
#endif

Then the code for the features would look like:

void DoFeatures()
{
#if USING( FEATURE_A )
    // Feature A code...
#endif

#if USING( FEATURE_B )
    // Feature B code...
#endif

#if USING( FEATURE_C )
    // Feature C code...
#endif

#if USING( FEATURE_D ) // Compile error since FEATURE_D was never defined
    // Feature D code...
#endif
}

My question (the part I don't remember) is how to define the 'USING' macro so that it errors if the feature hasn't been defined as 'IN_USE' or 'NOT_IN_USE'? Which could be the case if you forget to include the correct header file.

#define USING( feature ) ((feature == IN_USE) ? 1 : ((feature == NOT_IN_USE) ? 0 : COMPILE_ERROR?))

回答1:

Your example already achieves what you want, since #if USING(x) will produce an error message if USING isn't defined. All you need in your header file is something like

#define IN_USE 1
#define NOT_IN_USE 0
#define USING(feature) feature

If you want to be sure that you also get an error just for doing something like

#if FEATURE

or

#if USING(UNDEFINED_MISPELED_FEETURE)

then you could do, say,

#define IN_USE == 1
#define NOT_IN_USE == 0
#define USING(feature) 1 feature

but you won't be able to prevent such misuse as

#ifdef FEATURE


回答2:

The following works. It will give you compile error for FEATURE_D. If you comment out the code for FEATURE_D, then it will execute code for FEATURE_A and FEATURE_B. The code is pretty much self-explanatory. Instead of checking whether FEATURE_D or others are defined inside DoFeatures function, you can just put them inside an if block. In that way, the compiler will try to execute the code block. If it is 1, then the code inside if block will get executed; in case of 0, it will not get executed. And if it is never defined, then will get a compile error.

#include <stdio.h>

#define IN_USE      1
#define NOT_IN_USE  0

#define FEATURE_A       IN_USE
#define FEATURE_B       IN_USE
#define FEATURE_C       NOT_IN_USE


void DoFeatures()
{
    if(FEATURE_A){
        // Feature A code...
        printf("Feature A\n");
    }

    if(FEATURE_B){
        // Feature B code...
        printf("Feature B\n");
    }

    if(FEATURE_C){
        // Feature C code...
        printf("Feature C\n");
    }

    if(FEATURE_D) {// Compile error since FEATURE_D was never defined
        // Feature D code...
        printf("Feature D\n");
    }
}

int main(int argc, char **argv)
{
    DoFeatures();
    return 0;
}


回答3:

Just don't define it if it is not in use

#if defined( WIN32 )
    #define FEATURE_A       
    #define FEATURE_B       
#else if defined( OSX )
    #define FEATURE_C      
#else

#endif

Then In you code:

void DoFeatures()
{
#ifdef FEATURE_A
    // Feature A code...
#endif

#ifdef FEATURE_B
    // Feature B code...
#endif

#ifdef FEATURE_C
    // Feature C code...
#endif

#ifdef FEATURE_D // Compile error since FEATURE_D was never defined
    // Feature D code...
#endif
}


回答4:

Couldn't you just use another group of #ifdefs?

#if defined(WIN32)
    #define FEATURE_A
    #define FEATURE_B
#elif defined (OSX)
    #define FEATURE_C
#endif

// ...

#if defined(FEATURE_A)
    do_a();
#endif

etc.



回答5:

#define IN_USE      1
//#define NOT_IN_USE  _  //Not required


#if defined( WIN32 )
    #define FEATURE_A       IN_USE
    #define FEATURE_B       IN_USE
    #define FEATURE_C       NOT_IN_USE
#elif defined( OSX )
    #define FEATURE_A       NOT_IN_USE
    #define FEATURE_B       NOT_IN_USE
    #define FEATURE_C       IN_USE
#else
    #define FEATURE_A       NOT_IN_USE
    #define FEATURE_B       NOT_IN_USE
    #define FEATURE_C       NOT_IN_USE
#endif

#define USING( feature ) feature

And then your code



回答6:

How about something like this?

#define IN_USE      1
#define NOT_IN_USE  0

#if defined( WIN32 )
    #define FEATURE_A       IN_USE
    #define FEATURE_B       IN_USE
    #define FEATURE_C       NOT_IN_USE
#elif defined( OSX )
    #define FEATURE_A       NOT_IN_USE
    #define FEATURE_B       NOT_IN_USE
    #define FEATURE_C       IN_USE
#else
    #define FEATURE_A       NOT_IN_USE
    #define FEATURE_B       NOT_IN_USE
    #define FEATURE_C       NOT_IN_USE
#endif

#define USING(f) ((f == IN_USE) ? 1 : (f == NOT_IN_USE) ? 0 : (f))

#include <stdio.h>

void DoFeatures()
{
#if USING( FEATURE_A )
    // Feature A code...
    printf("Feature A\n");
#endif

#if USING( FEATURE_B )
    // Feature B code...
    printf("Feature B\n");
#endif

#if USING( FEATURE_C )
    // Feature C code...
    printf("Feature C\n");
#endif

#if defined( FEATURE_D ) // Compile error since FEATURE_D was never defined
    // Feature D code...
    printf("Feature D\n");
#else
#error FEATURE_D not defined.
#endif
}

int main(int argc, char **argv)
{
    DoFeatures();
    return 0;
}

For the compilation error, I have no idea how to integrate it into the macro. It would be appreciated if somebody could shed us some light. :P