I need to generate a series of sequential numbers throughout my code at compile time. I tried "__COUNTER__" in a way like this:
void test1()
{
printf("test1(): Counter = %d\n", __COUNTER__);
}
void test2()
{
printf("test2(): Counter = %d\n", __COUNTER__);
}
int main()
{
test1();
test2();
}
And the result was perfect as I expected:
test1(): Counter = 0
test2(): Counter = 1
Then I spread "__COUNTER__" out in different .cpp files:
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;
}
The result was:
Foo::Foo() with counter = 0
Bar::Bar() with counter = 0
It looks to me that "__COUNTER__" is provided as a per compile unit variable.
What I'd like to have is a global counter that's effective throughout the code.
This is used for testing in a debug build where I want to achieve this goal:
Imagine that I have try/catch blocks throughout the code (a subsystem or a module within multiple .cpp files). At run time the program is running in a loop, within each loop all the try blocks will be executed in orders (in which order doesn't matter), and I want to test how the code react to exception for each try/catch, one by one. For example, the first time in the loop, #1 try/catch block throws an exception; second time in the loop, #2 try/catch block throws an exception, etc etc.
I plan to have a global counter like this:
int g_testThrowExceptionIndex = 0;
In each try/catch:
try
{
TEST_THROW_EXCEPTION(__COUNTER__)
//My logic is here...
}
catch(...)
{
//Log or notify...
}
And the Macro would be something like this:
#define TEST_THROW_EXCEPTION(n) \
if(g_testThrowExceptionIndex == n)\
{\
g_testThrowExceptionIndex++;\
throw g_testThrowExceptionIndex;\
}\
Without the ability to generate the sequence number at compile time, I have to write the Macro like this:
TEST_THROW_EXCEPTION(THROW_INDEX_1)
......
TEST_THROW_EXCEPTION(THROW_INDEX_N)
And in the header, defines:
#define THROW_INDEX_1 0
#define THROW_INDEX_2 1
......
The problem is, every time you add a try/catch block and you want to test, you have to create a new constant through #define and put that number into the Macro. Worse, what if you remove some of the try/catch blocks from the code? You have to update your #define list too...
==============
Solution: Thanks for Suma's idea, I ended up with something like this:
#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
In main.cpp:
#if defined(_DEBUG) && defined(_EXCEPTION_TEST)
int g_testThrowExceptionIndex= 0;
int GCounter::counter= 0;
#endif
Then you can put "TEST_THROW_EXCEPTION" in any of your try/catch block you want to test out.
__COUNTER__
within those causes even more problems. Suma's +1 solution is nicely portable and sidesteps preprocessing issues. – Armrest