OK, I’m trying to do some tricky preprocessor stuff, and I’ve gotten a bit stuck.
Basically, I want to be able to have something like this at the top of a C file:
TEST(10,20)
TEST(30,40)
TEST(50,60)
which expands to
testStruct unique1(10,20);
testStruct unique2(30,40);
testStruct unique3(50,60);
basically, each time the macro is evaluated, I need it to generate a unique identifier that is part of its expansion.
I tried to do that using the LINE macro, something like this:
#define TEST(a,b) testStruct unique## LINE(a,b);
the trouble is, the ## gets evaluated first, resulting in unique__LINE__, and then I end up with multiple testStructs called unique__LINE__.
Does anyone have any crafty suggestions as to how to get around this? Or an alternate strategy that would accomplish what I’m trying to accomplish?
Sorry, I have no real solution for your problem. Just a suggestion: You could make you macro call a function that includes that information, or even a macro that substitutes for another macro that calls a function. Of course, if you are after a unique identifier after the preprocessor pass, my “solution” doesn´t work.
What I´m suggesting is:
#define TEST(a,b) test(FILE, LINE, a, b)
and then have some (global) function test() that does what you want.
or
#define TEST1(a, b) TEST2(FILE, LINE, a, b) #define TEST2(f, l, a, b) test (f, l, a, b)
and so on.
That only affects the arguments to your call. If want to create an unique token after the preprocessor pass, I´m not sure what you could do. I think I remenber some usage of /* and */ to concatenate SOMETHING in the preprocessor, but I would have to look that up.
z_z_z’s suggestion to use two macros almost works. A third puts it over the top.
#define CONCAT(a,b) a ## b
#define TEST2(a,b,c) testStruct CONCAT(unique,c)(a,b);
#define TEST(a,b) TEST2(a,b,__LINE__)
However, I’m having a hard time thinking of of a situation where this would be useful. Perhaps you could share what problem you’re trying to solve with the uniquely-named identifiers and we could come up with a even better solution.
I reread your OP and wonder - what are you excactly trying to accomplish?
Are you after a unique token after the preprocessor pass? Or just some way to distiguish between different “calls” to your macro, even if the arguments are the same?
I´m just guessing, but if it is the latter, and you want to differentiate between
<line 123> TEST(20, 20)
and
<line 234> TEST(20, 20)
and have some sort of sequential numbering, then you could try the following
#define TEST(a, b) test(get_num(), a, b)
and have a array of test_struct[MAX]
and reference test_struct* in test(i, a, b) and of course a global function get_num() that returns sequential numbers 0…MAX - 1.
Sorry if this is not what you´re after, but tell us more…
And yes, ## is what I had in mind, instead of /* and */. I can´t look it up now, but does´t this also have some use in the preprocessor, or did I cofuse the two?
Before a##b was widely supported, people used to use a/**/b to concatenate, trusting the preprocessor to remove comments after replacing macro arguments without leaving a space. That’s deprecated now.
If you want a picture of what’s going on in time-sensitive code, or an environment with a lot of threads, something like this can be handy, as you can pass off all the output to another program. My employer has something like this, but we have a whole system set up to generate unique IDs.
z_z_z’s solution is probably about as good as you’re going to get without something like that, but it seems like it would only work for a single file–if two TEST statements are on the same line in different files, you wouldn’t be able to distinguish them.
FILE returns the current source file’s name as a string. You can’t put it in an identifier, but you can pass it to the constructor; collisions will only be a problem if the identifiers are global.
I could’ve sworn that we used that as part of a macro at work, as a parameter to a printf statement. It looks like I’ll have an opportunity to check it out tomorrow. :mad:
There might also be a way to do this with templates, but there are a couple issues there:
It’ll slow your compilation to a crawl. That might not be really bad, but it is something to consider.
No compiler handles templates correctly, and no two compilers mishandle them in exactly the same way. If this for only one compiler, that might not be an issue.
The more I think about this, the more confused I get. What are you trying to identify here? Do you just want to create a new object of type testStruct?
That looks like it from the desired sample code in the OP.
Since there’s no way to refer to these objects (without knowing which line they were created on, which will change constantly as you add code), and since a constructor call for an object you’ll never use is just a function call with a memory leak (temporary, if it’s on the stack), I can only assume the point is to do something when the object is automatically destructed - write a log message, release a lock that was acquired in the constructor, etc.
#define UNIQUE_ID (__LINE__ << 24) + (atoi(__TIME__) << 16) + (atoi(&__TIME__[3]) << 8) + atoi(&__TIME__[6])
#define TEST(a, b) testStruct<UNIQUE_ID>(a, b)
template <int n> struct testStruct
{
....put whatever you need in here
};
Now, that does have the problem that the value of UNIQUE_ID will change whenever you add or delete code, and whenever you recompile. But if you don’t care about that, it’s not a problem.
ultrafilter’s template example should work. Here is a CodeProject article that uses the same technique (scroll to the paragraph just before Conclusion). The nice thing about this article is that he walks the logic up to the final solution.
Instead of trying to do it in the preprocessor, I would make a simple perl script and integrate that into a makefile which gives you much more flexibility and the removal of nasty side-effects that macros can sometimes lend to the code.
Thanks for all the advice and answers… one of my coworkers came up with a 3-macro solution similar to the one proposed by John T. Conklin, although I would have to go reread the K&R chapter about the preprocessor to really be certain I understood what was going on.
As for what it’s for, Mr2001’s guess is almost right… I’m using a dummy class which takes up no space, but whose constructor function contains snippets of code that I want to make sure run before anything else (well, anything not in a constructor function for a static object) runs. For instance, I might want to register various static variables of various classes with some central debug system. So, I’d have a function like DebugSystem()::RegisterVariable(void *pVar, enumVarType eType, char *pName), and I might have variables to register scattered around between different files and modules, Render, Events, Physics, Collision. So obviously I could just add calls to DebugSystem()::RegisterVariable() into init functions for each of these modules, but that assumes there ARE init functions for each of these modules, that they’re all called before anything important happens, etc.
Using cool macros of this sort, I can just stick a REGISTER_VARIABLE macro at file scope, and I know that the code will get called once and only once at startup time.
(It wouldn’t surprise me if there were a more efficient way to do this… but my C++ knowledge was acquired in a somewhat ad hoc fashion.)
Wow. Sorry, i don´t want to shout, but DON´T DO THIS!!!
That´s not how macros work. The preprocessor is simply a (parametric) text replacement tool that runs before the code is actually compiled. NO functions/methods/constructors or whatever will be called and no code will be excuted by the text replacement.
If you have a macro
#define TEST(a) exit(a)
then the preprocessor simply replaces each occurence of TEST(a) with exit(a), with “a” being a parameter. No code will be excuted. Then the resulting programm is compiled. Think of it like having a sed or perl script in your makefile and passing the output of this script to the compiler.
I think he’s suggesting that his macros are being used at file scope and expand into object definitions. The constructors for such objects are called before the execution of the main program, which seems to be what he wants. E.g., if I have a macro
#define TEST(a,b) TestObj a(b)
(where TestObj is some class with constructor TestObj(int) ) and I have
TEST(x,3); // expands to TestObj x(3);
int main( ) { TestObj(y,4); }
at file scope, then the constructor TestObj(3) will be called before TestObj(4). The macros are simply a way to generate the appropriate inputs to the constructor from the preprocessor’s LINE macro.