如何构造本地唯一标识符名称

How can I construct a locally unique identifier name?

本文关键字:标识符 唯一 何构造      更新时间:2023-10-16

我想动态创建一个唯一的变量名称。

这是我的代码:

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中递归扩展参数placeline之后。 您可以通过将##操作移动到单独的宏来做到这一点 - 只要##没有出现在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__并确保最终可以在不同的编译单元中产生重复项的事实不是问题(如果它们是某个函数的本地,那应该没问题,或者您可以将它们放在匿名命名空间中。