C++ Preprocessor metaprogramming: obtaining an unique value?
I'm exploiting the behavior of the constructors of C++ global variables to run code at startup in a simple manner. It's a very easy concept but a little difficult to explain so let me just paste the code:
struct _LuaVariableRegistration
{
template<class T>
_LuaVariableRegistration(const char* lua_name, const T& c_name) {
/* ... This code will be ran at startup; it temporarily saves lua_name and c_name in a std::map and when Lua is loaded it will register all temporarily global variables in Lua. */
}
};
However manually instantiating that super ugly class every time one wants to register a Lua global variable is cumbersome; that's why I created the following macro:
#define LUA_GLOBAL(lua_name, c_name) static Snow::_LuaVariableRegistration _____LuaGlobal ## c_name (lua_name, c_name);
So all you have to do is put that in the global scope of a cpp file and everything works perfectly:
LUA_GLOBAL("LuaIsCool", true);
There you go! Now in Lua LuaIsCool
will be a variable initialized to true!
But, here is the problem:
LUA_GLOBAL("ACCESS_NONE", Access::None);
Which becomes:
static Snow::_LuaVariableRegistration _____LuaGlobalAccess::None ("ACCESS_NONE", &Access::None);
:((
I need to concatenate c_name
in the m开发者_如何学编程acro or it will complain about two variables with the same name; I tried replacing it with __LINE__
but it actually becomes _____LuaGlobalAccess__LINE__
(ie it doesn't get replaced).
So, is there a way to somehow obtain an unique string, or any other workaround?
PS: Yes I know names that begin with _ are reserved; I use them anyway for purposes like this being careful to pick names that the standard library is extremely unlikely to ever use. Additionally they are in a namespace.
You need to add an extra layer of macros to make the preprocessor do the right thing:
#define TOKENPASTE(x, y) x ## y
#define TOKENPASTE2(x, y) TOKENPASTE(x, y)
#define LUA_GLOBAL(lua_name, c_name) ... TOKENPASTE2(_luaGlobal, __LINE__) ...
Some compilers also support the __COUNTER__
macro, which expands to a new, unique integer every time it is evaluated, so you can use that in place of __LINE__
to generate unique identifiers. I'm not sure if it's valid ISO C, although gcc accepts its use with the -ansi -pedantic
options.
精彩评论