Средство препроцессора __COUNTER__ в Visual C ++

Мне нужно сгенерировать серию последовательных чисел во всем моем коде во время компиляции. Я попробовал «__COUNTER__» следующим образом:

void test1()
{
  printf("test1(): Counter = %d\n", __COUNTER__);
}
void test2()
{
  printf("test2(): Counter = %d\n", __COUNTER__);
}
int main()
{
  test1();
  test2();
}

И результат был идеальным, как я ожидал:

test1(): Counter = 0
test2(): Counter = 1

Затем я распространил «__COUNTER__» на разные файлы .cpp:

In Foo.cpp:
Foo::Foo()
{
  printf("Foo::Foo() with counter = %d\n", __COUNTER__);
}
In Bar.cpp:
Bar::Bar()
{
  printf("Bar::Bar() with counter = %d\n", __COUNTER__);
}

In Main.cpp:
int main()
{
  Foo foo;
  Bar bar;
}

Результат был:

Foo::Foo() with counter = 0
Bar::Bar() with counter = 0

Это мне кажется, что «__COUNTER__» предоставляется как переменная для каждого модуля компиляции .

Я бы хотел иметь глобальный счетчик, действующий во всем коде.

Он используется для тестирования в отладочной сборке, где я хочу достичь этой цели:

Представьте, что у меня есть блоки try / catch по всему коду (подсистема или модуль в нескольких файлах .cpp). Во время выполнения программа работает в цикле, внутри каждого цикла все блоки try будут выполняться по порядку (в каком порядке не имеет значения), и я хочу проверить, как код реагирует на исключение для каждой попытки / улова, по одному. Например, в первый раз в цикле блок try / catch №1 вызывает исключение; второй раз в цикле блок try / catch # 2 генерирует исключение и т. д.

Я планирую иметь такой глобальный счетчик:

int g_testThrowExceptionIndex = 0;

В каждом try / catch:

try
{
  TEST_THROW_EXCEPTION(__COUNTER__)
  //My logic is here...
}
catch(...)
{
  //Log or notify...
}

И макрос будет чем-то вот так:

#define TEST_THROW_EXCEPTION(n) \
        if(g_testThrowExceptionIndex == n)\
        {\
          g_testThrowExceptionIndex++;\
          throw g_testThrowExceptionIndex;\
        }\

Без возможности генерировать порядковый номер во время компиляции я должен написать макрос следующим образом:

TEST_THROW_EXCEPTION(THROW_INDEX_1)
......
TEST_THROW_EXCEPTION(THROW_INDEX_N)

А в заголовке определяет:

#define THROW_INDEX_1 0
#define THROW_INDEX_2 1
......

Проблема в том, что каждый раз, когда вы добавляете попытку / catch, и вы хотите протестировать, вам нужно создать новую константу с помощью #define и поместить это число в макрос. Хуже того, что, если вы удалите из кода некоторые блоки try / catch? Вам также необходимо обновить свой список #define ...

==============

Решение: Спасибо за идею Suma, у меня получилось примерно следующее:

#if defined(_DEBUG)  && defined(_EXCEPTION_TEST)
  extern int g_testThrowExceptionIndex;
  struct GCounter
  {
    static int counter; // used static to guarantee compile time initialization
    static int NewValue() {return counter++;}
  };
  #define TEST_THROW_EXCEPTION \
      static int myConst = GCounter::NewValue();\
      if(g_testThrowExceptionIndex == myConst)\
      {\
        g_testThrowExceptionIndex++;\
        throw 0;\
      }
#else
  #define TEST_THROW_EXCEPTION 
#endif

В main.cpp:

#if defined(_DEBUG) && defined(_EXCEPTION_TEST)
  int g_testThrowExceptionIndex= 0;
  int GCounter::counter= 0;
#endif

Затем вы можете поместить «TEST_THROW_EXCEPTION» в любой блок try / catch, который хотите проверить.

7
задан Ping 5 August 2011 в 15:24
поделиться