David Citron
David Citron

Reputation: 43619

C++ conditional macro evaluation

I have a symbol defined globally that needs to be conditionally undefined for a given subset of my source files. All of the files that require special treatment are already wrapped in pre- and post-inclusions:

pre.h:

#undefine mysymbol // [1]

post.h:

#define mysymbol MY_SYMBOL_DEFINITION // [2]

My problem is that the pre.h and post.h can be included multiple times for a given source file due to various inclusion chaining. As such, I need 1 to happen the first time pre.h is included and I need 2 to happen the last time that post.h is included. Conceptually:

pre         // undefine
   pre      // no-op
      pre   // no-op
      post  // no-op
   post     // no-op
post        // redefine

Since I am using GCC 3.4.6, I do not have access to the push and pop macro pragmas that might otherwise solve this issue for me.

How can I emulate that behavior with the remaining preprocessor functionality?

I was attempting to do something like increment/decrement a value with the preprocessor, but I'm not sure that's possible.

"What am I really trying to do?"

We have macros to replace new with new(__FILE__, __LINE__) -- see my other question on this topic -- and we need to undefine those macros in the set of source files wrapped by the pre- and post-includes described above because we were unable to create a macro that's compatible with the placement new syntax used therein.

Upvotes: 5

Views: 9268

Answers (5)

KitsuneYMG
KitsuneYMG

Reputation: 12901

Try:

File pre.h

#ifndef MYMACROGUARD
    #undef MYMACRO
    #define MYMACROGUARD MYMACROGUARD+1
#endif

File post.h

#if MYMACROGUARD <= 0
    #undef MYMACROGUARD
#else
    #define MYMACROGUARD MYMACROGUARD-1
#endif

Tested with this code

#define MYMACRO

#include<iostream>

using namespace std;
int main()
{
    #ifdef MYMACRO
        cout<<"1"<<endl;
    #endif

    #include <pre.h>

    #ifdef MYMACRO
        cout<<"2"<<endl;
    #endif

    #include <pre.h>

    #ifdef MYMACRO
        cout<<"3"<<endl;
    #endif

    #include <post.h>

    #ifdef MYMACRO
        cout<<"4"<<endl;
    #endif

    #include <post.h>

    #ifdef MYMACRO
        cout<<"5"<<endl;
    #endif
}

$> g++ -w -I. test.cpp && ./a.out

1
5

Upvotes: 0

Assaf Lavie
Assaf Lavie

Reputation: 76103

Incrementing/decrementing a value at compile time is probably possible with meta-programming wizardry a-la Loki. But are you sure this is necessary?

Why is your h file included so many time? Why not use an include guard?

Upvotes: 0

nusi
nusi

Reputation: 1026

pre.h

#ifndef MYSYMBOLUNDEFFERSTACK
#define MYSYMBOLUNDEFFERSTACK 0
#else
#define MYSYMBOLUNDEFFERSTACKTMP (MYSYMBOLUNDEFFERSTACK+1)
#undef MYSYMBOLUNDEFFERSTACK
#define MYSYMBOLUNDEFFERSTACK MYSYMBOLUNDEFFERSTACKTMP
#undef MYSYMBOLUNDEFFERSTACKTMP
#endif

#if MYSYMBOLUNDEFFERSTACK == 0
#undef mysymbol
#endif

post.h

#ifndef MYSYMBOLUNDEFFERSTACK
#error "Async Post.h"
#else
#define MYSYMBOLUNDEFFERSTACKTMP (MYSYMBOLUNDEFFERSTACK-1)
#undef MYSYMBOLUNDEFFERSTACK
#define MYSYMBOLUNDEFFERSTACK MYSYMBOLUNDEFFERSTACKTMP
#undef MYSYMBOLUNDEFFERSTACKTMP
#endif

#if MYSYMBOLUNDEFFERSTACK == 0
#define mysymbol "MY_SYMBOL_DEFINITION"
#endif

Which works fine in this case:

#include "stdio.h"
#include "pre.h"
#include "pre.h"
#include "pre.h"
//const char *pCompileError = mysymbol;
#include "post.h"
//const char *pCompileError = mysymbol;
#include "post.h"
//const char *pCompileError = mysymbol;
#include "post.h"

int main(void)
{
    const char *p = mysymbol;
    printf("%s\n", p);
    return 0;
}

Edit: Works fine with gcc 4.0.

Upvotes: 0

klew
klew

Reputation: 14977

You can add somethig like this to your pre.h file:

... 

#ifdef COUNT
#if COUNT == 2
#undef COUNT
#define COUNT 3
#endif

#if COUNT == 1
#undef COUNT
#define COUNT 2
#endif

#else
#define COUNT 1

... here put your pre.h code

#endif

And in post.h:

#ifdef COUNT
#if COUNT == 1
#undef COUNT
#endif

#if COUNT == 2
#undef COUNT
#define COUNT 1
#endif

#if COUNT == 3
#undef COUNT
#define COUNT 2
#endif

...    

#end

#ifndef COUNT

... here put your pre.h code

#endif

But you need to know how deep can you go.

Upvotes: 4

Ben Murphy
Ben Murphy

Reputation:

If you know the maximum depth of recursion, then you should be able to simulate the push/pop by defining a new macro at each level. For the 3 level example you give, that would look something like:

Pre.h:

#ifdef RECURSION_COUNT_1
 #ifdef RECURSION_COUNT_2
  #ifdef RECURSION_COUNT_3
   #error Recursion level too deep
  #else
   #define RECURSION_COUNT_3
  #endif
 #else
  #define RECURSION_COUNT_2
 #endif
#else
 #define RECURSION_COUNT_1
 #undef YOUR_SYMBOL_HERE
#endif

Post.h

#ifdef RECURSION_COUNT_3
 #undef RECURSION_COUNT_3
#else
 #ifdef RECURSION_COUNT_2
  #undef RECURSION_COUNT_2
 #else
  #ifdef RECURSION_COUNT_1
   #undef RECURSION_COUNT_1
   #define YOUR_SYMBOL_HERE
  #endif
 #endif
#endif

Upvotes: 0

Related Questions