Visual C++中的预处理器工具__COUNTER__

Pin*_*ing 7 c++ counter visual-studio c-preprocessor

我需要在编译时在代码中生成一系列序列号.我用这样的方式尝试了"__COUNTER__":

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

结果如我所料完美:

test1(): Counter = 0
test2(): Counter = 1
Run Code Online (Sandbox Code Playgroud)

然后我在不同的.cpp文件中传播"__COUNTER__":

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;
}
Run Code Online (Sandbox Code Playgroud)

结果是:

Foo::Foo() with counter = 0
Bar::Bar() with counter = 0
Run Code Online (Sandbox Code Playgroud)

在我看来,"__ COUNTER__"作为每个编译单元变量提供.

我想拥有的是一个在整个代码中都有效的全局计数器.

这用于在我希望实现此目标的调试版本中进行测试:

想象一下,我在整个代码中尝试/捕获块(子系统或多个.cpp文件中的模块).在运行时程序循环运行,每个循环中的所有try块将在订单执行中(其中顺序并不重要),我想测试代码如何反应异常为每个try/catch语句,逐一.例如,第一次在循环中,#1 try/catch块抛出异常; 第二次在循环中,#2 try/catch块抛出异常等等.

我计划有一个这样的全球计数器:

int g_testThrowExceptionIndex = 0;
Run Code Online (Sandbox Code Playgroud)

在每个try/catch中:

try
{
  TEST_THROW_EXCEPTION(__COUNTER__)
  //My logic is here...
}
catch(...)
{
  //Log or notify...
}
Run Code Online (Sandbox Code Playgroud)

宏将是这样的:

#define TEST_THROW_EXCEPTION(n) \
        if(g_testThrowExceptionIndex == n)\
        {\
          g_testThrowExceptionIndex++;\
          throw g_testThrowExceptionIndex;\
        }\
Run Code Online (Sandbox Code Playgroud)

如果没有在编译时生成序列号的能力,我必须像这样编写宏:

TEST_THROW_EXCEPTION(THROW_INDEX_1)
......
TEST_THROW_EXCEPTION(THROW_INDEX_N)
Run Code Online (Sandbox Code Playgroud)

在标题中,定义:

#define THROW_INDEX_1 0
#define THROW_INDEX_2 1
......
Run Code Online (Sandbox Code Playgroud)

问题是,每次添加try/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
Run Code Online (Sandbox Code Playgroud)

在main.cpp中:

#if defined(_DEBUG) && defined(_EXCEPTION_TEST)
  int g_testThrowExceptionIndex= 0;
  int GCounter::counter= 0;
#endif
Run Code Online (Sandbox Code Playgroud)

然后,您可以在要测试的任何try/catch块中放入"TEST_THROW_EXCEPTION".

Sum*_*uma 5

您无法使用预处理器执行此操作,因为每个编译单元都是单独预处理的.为此需要运行时解决方案.您可以创建一个全局单例,并且每个需要唯一标识符的位置都可以使用此单例定义静态int.

struct GCounter
{
  static int counter; // used static to guarantee compile time initialization
  static int NewValue() {return counter++;}
};

int GCounter::counter = 0;

void Foo1()
{
  static int ID1 = GCounter::NewValue();
}

void Foo2()
{
  static int ID2 = GCounter::NewValue();
}
Run Code Online (Sandbox Code Playgroud)

注意:未定义多个编译单元中的那些静态值(ID)的初始化顺序.您可以确定它们将始终是唯一的,但您不能依赖它们具有某些特定值或排序.因此,例如将它们保存到文件中时要小心 - 您应该将它们转换为某种中性表示.