我想动态创建一个唯一的变量名。
这是我的代码:
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:语法错误:缺少';'在'常数'之前
test.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;
}
答案 0 :(得分:3)
对于唯一标识符,许多实现都提供__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
答案 1 :(得分:2)
您需要延迟令牌粘贴,直到参数place
和line
在宏CALL_LATER2
中递归展开。您可以通过将##
操作移动到单独的宏来执行此操作 - 只要##
未出现在CALL_LATER2
的正文中,其所有参数都将针对宏进行预扫描:< / p>
#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__
,并确保您可以在不同的编译单元中最终得到重复的事实不是问题(如果它们是某些函数的本地名称,那应该没问题,或者你可以把它们放在一个匿名的命名空间里。)