我正在利用C ++全局变量的构造函数的行为以简单的方式在启动时运行代码。这是一个非常简单的概念,但有点难以解释,所以让我只需粘贴代码:
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. */
}
};
然而,每次想要注册Lua全局变量时手动实例化那个超级丑陋的类是很麻烦的;这就是我创建以下宏的原因:
#define LUA_GLOBAL(lua_name, c_name) static Snow::_LuaVariableRegistration _____LuaGlobal ## c_name (lua_name, c_name);
所以你要做的就是把它放在cpp文件的全局范围内,一切都很完美:
LUA_GLOBAL("LuaIsCool", true);
你去吧!现在在Lua中LuaIsCool
将变量初始化为true!
但是,问题在于:
LUA_GLOBAL("ACCESS_NONE", Access::None);
哪个成为:
static Snow::_LuaVariableRegistration _____LuaGlobalAccess::None ("ACCESS_NONE", &Access::None);
:((
我需要在宏中连接c_name
,否则它会抱怨两个具有相同名称的变量;我尝试用__LINE__
替换它,但它实际上变为_____LuaGlobalAccess__LINE__
(即它不会被替换)。
那么,有没有办法以某种方式获得一个唯一的字符串,或任何其他解决方法?
PS:是的我知道以_开头的名字是保留的;我仍然使用它们来达到这样的目的,即小心选择标准库极不可能使用的名称。此外,它们位于命名空间中。
答案 0 :(得分:7)
你需要添加一层额外的宏来使预处理器做正确的事情:
#define TOKENPASTE(x, y) x ## y
#define TOKENPASTE2(x, y) TOKENPASTE(x, y)
#define LUA_GLOBAL(lua_name, c_name) ... TOKENPASTE2(_luaGlobal, __LINE__) ...
某些编译器也支持__COUNTER__
宏,每次评估时都会扩展为一个新的唯一整数,因此您可以使用它来代替__LINE__
来生成唯一标识符。我不确定它是否是有效的ISO C,尽管gcc接受它与-ansi -pedantic
选项一起使用。