C ++ условная оценка макроса - PullRequest
5 голосов
/ 26 марта 2009

У меня есть символ, определенный глобально, который должен быть условно неопределенным для данного подмножества моих исходных файлов. Все файлы, требующие особой обработки, уже обернуты до и после включения:

pre.h:

#undefine mysymbol // [1]

post.h:

#define mysymbol MY_SYMBOL_DEFINITION // [2]

Моя проблема в том, что pre.h и post.h могут быть включены несколько раз для данного исходного файла из-за различных цепочек включения. Таким образом, мне нужно, чтобы 1 произошло в первый раз, когда включен pre.h, и мне нужно, чтобы 2 произошло в последний раз , в который включено post.h. Концептуально:

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

Поскольку я использую GCC 3.4.6, у меня нет доступа к макросам push и pop макросов , которые в противном случае могли бы решить эту проблему для меня.

Как мне эмулировать это поведение с оставшейся функциональностью препроцессора?

Я пытался сделать что-то вроде увеличения / уменьшения значения с препроцессором, но я не уверен, что это возможно.

«Что я действительно пытаюсь сделать?»

У нас есть макросы для замены new на new(__FILE__, __LINE__) - см. мой другой вопрос по этой теме - и нам нужно отменить определение этих макросов в наборе исходных файлов, обернутых предварительно и post-include, описанные выше, потому что мы не смогли создать макрос, совместимый с используемым в нем новым синтаксисом размещения.

Ответы [ 5 ]

4 голосов
/ 26 марта 2009

Вы можете добавить что-нибудь подобное в файл pre.h:

... 

#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

И в 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

Но тебе нужно знать, как глубоко ты можешь зайти.

0 голосов
/ 26 марта 2009

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

Что отлично работает в этом случае:

#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: Отлично работает с gcc 4.0.

0 голосов
/ 26 марта 2009

Попробуйте:

Файл pre.h

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

Файл post.h

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

Проверено с этим кодом

#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
0 голосов
/ 26 марта 2009

Если вы знаете максимальную глубину рекурсии, то вы сможете смоделировать push / pop путем определения нового макроса на каждом уровне. Для примера с 3 уровнями это будет выглядеть примерно так:

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
0 голосов
/ 26 марта 2009

Увеличение / уменьшение значения во время компиляции, возможно, возможно с помощью мастера метапрограммирования а-ля Локи Но вы уверены, что это необходимо?

Почему ваш файл h включен так много раз? Почему бы не использовать охранник включения?

...