如何构造本地唯一标识符名称
How can I construct a locally unique identifier name?
我想动态创建一个唯一的变量名称。
这是我的代码:
int call(int i)
{
return i;
}
#define XCAT3(a, b, c) a ## b ## c
#define CALL_2(arg, place, line) int XCAT3(cl, place, line) = call(arg);
#define CALL_1(arg) CALL_2(arg, __FUNCTION__, __LINE__)
int main(int argc, char* argv[])
{
CALL_1(1); /* this is line 20 */
return 0;
}
这在GCC(http://ideone.com/p4BKQ)中确实有效,但不幸的是在Visual Studio 2010或2012中不起作用。
错误消息是:
test.cpp(20):错误 C2143:语法错误:function_string"之前缺少";"
test.cpp(20):错误 C2143:语法错误:在"常量"之前缺少";"
测试.cpp(20):错误 C2106:"=":左操作数必须是 L 值
如何使用C++创建动态的唯一变量名称?
溶液:
#define CAT2(a,b) a##b
#define CAT(a,b) CAT2(a,b)
#define UNIQUE_ID CAT(_uid_,__COUNTER__)
int main(int argc, char* argv[])
{
int UNIQUE_ID = 1;
int UNIQUE_ID = 2;
return 0;
}
对于唯一标识符,许多实现都提供__COUNTER__
预处理器宏,每次使用都会扩展到不断增加的数量。
#define CAT(a,b) CAT2(a,b) // force expand
#define CAT2(a,b) a##b // actually concatenate
#define UNIQUE_ID() CAT(_uid_,__COUNTER__)
auto UNIQUE_ID() = call(1); // may be _uid_0
auto UNIQUE_ID() = call(2); // may be _uid_1
您需要
将令牌粘贴推迟到宏CALL_LATER2
中递归扩展参数place
和line
之后。 您可以通过将##
操作移动到单独的宏来做到这一点 - 只要##
没有出现在CALL_LATER2
的主体中,它的所有参数都将被预先扫描为宏:
#define XCAT3(a, b, c) a ## b ## c
#define CALL_LATER2(fun, h, place, line)
auto XCAT3(calllater, place, line) =
call_later((fun), (h));
但是,这仍然不会做你想要的,因为__FUNCTION__
扩展到包含"
个字符的字符串,而不是可以粘贴到标识符中的内容。 相反,您只需将创建的名称基于__LINE__
并确保最终可以在不同的编译单元中产生重复项的事实不是问题(如果它们是某个函数的本地,那应该没问题,或者您可以将它们放在匿名命名空间中。
相关文章:
- 如何在C++中为增加但记住删除先前对象的对象分配唯一标识符
- 按唯一标识符描述数字列表
- 获取窗口监视器的唯一标识符
- 鼠标,键盘和其他HID设备的唯一标识符
- 从 Android 上的 c++ 获取唯一的设备标识符
- 没有成员作为唯一标识符的两个类实例的比较
- 在Windows中获得C 中的唯一硬件标识符
- 如何构造本地唯一标识符名称
- 在编译时生成唯一的类型标识符
- 如何将目录路径转换为唯一的数字标识符 (Linux/C++)
- 获取系统的唯一标识符(而不是MAC地址)
- 生成可以区分 ID(Foo::a()) 和 ID(Foo::b()) 的唯一标识符
- 为iOS设备创建唯一标识符
- 如何获取计算机的唯一标识符
- CRTP和唯一的持久标识符
- 如何以跨平台的方式获得(几乎)唯一的系统标识符
- 为类型分配唯一的整型标识符,编译时
- protocolbuffers-c++唯一的持久类标识符
- 缩短唯一标识符
- 通过类型标识符表示类的数字唯一标识符