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

时间:2012-10-02 20:23:41

标签: c++ visual-studio-2010 visual-c++ uniqueidentifier c-preprocessor

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

这是我的代码:

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;
}

2 个答案:

答案 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)

您需要延迟令牌粘贴,直到参数placeline在宏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__,并确保您可以在不同的编译单元中最终得到重复的事实不是问题(如果它们是某些函数的本地名称,那应该没问题,或者你可以把它们放在一个匿名的命名空间里。)