【问题标题】:C++ Preprocessor metaprogramming: obtaining an unique value?C++ 预处理器元编程:获得独特的价值?
【发布时间】:2009-11-23 04:43:36
【问题描述】:

我正在利用 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:是的,我知道以 _ 开头的名称是保留的;无论如何,我将它们用于这样的目的,小心选择标准库极不可能使用的名称。此外,它们位于命名空间中。

【问题讨论】:

  • 注意 - 如果以下划线开头的标识符在命名空间中,则仅在其后跟大写字母时才保留。否则,您完全可以使用它。因此,将 '_Lua' 位更改为 '_lua' 就没有人可以抱怨了。至少关于那些(包含“____”的名称是另一回事)。
  • 不确定我明白你的意思.. 你为什么不连接lua_name 而不是c_name?那不是更有可能是独一无二的吗?
  • 无论如何,我相信stackoverflow.com/questions/1489932/… 可以解决您的“正确替换”问题。
  • @splicer:我不能,因为它是一个字符串。您可以使用#hi 从 hi 变为 hi,但不能从 hi 变为 hi。
  • 包含双下划线的名称怎么办?你知道这些规则吗?小心你的意思是你已经掌握了过去和未来的所有 UNIX 资源?如果你知道它违反了规则,为什么还要使用它?

标签: c++ lua c-preprocessor metaprogramming


【解决方案1】:

你需要额外添加一层宏来让预处理器做正确的事:

#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 选项一起使用。

【讨论】:

  • 谢谢,带有双宏的 COUNTER 似乎是最好的解决方案。我google了一下,它不是标准的,但是gcc和微软的编译器都支持它,这就是我的应用程序兼容的全部。
猜你喜欢
  • 2011-03-26
  • 1970-01-01
  • 2021-01-21
  • 1970-01-01
  • 2011-05-28
  • 1970-01-01
  • 2012-05-25
  • 2022-01-11
  • 1970-01-01
相关资源
最近更新 更多