开发者

C++ Preprocessor metaprogramming: obtaining an unique value?

开发者 https://www.devze.com 2022-12-12 00:28 出处:网络
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

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消