如何使用宏在C++中生成随机变量名?

fre*_*ass 17 c++ random variables macros naming

我正在用C++创建一个宏来声明一个变量并为它赋值.根据宏的使用方式,宏的第二次出现可以覆盖第一个变量的值.例如:

#define MY_MACRO int my_variable_[random-number-here] = getCurrentTime();
Run Code Online (Sandbox Code Playgroud)

使用它的另一个动机是避免为变量选择某个名称,以使其与开发人员最终使用宏选择的名称相同.

有没有办法在C++中的宏内生成随机变量名?

- 编辑 -

我的意思是独特但也是随机的,一旦我可以在一个块中使用我的宏两次,在这种情况下,它将生成如下:

int unique_variable_name;
...
int unique_variable_name;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,为了唯一,必须随机生成两个变量名.

Dav*_*son 25

请尝试以下方法:

// This is some crazy magic that helps produce __BASE__247
// Vanilla interpolation of __BASE__##__LINE__ would produce __BASE____LINE__
// I still can't figure out why it works, but it has to do with macro resolution ordering
#define PP_CAT(a, b) PP_CAT_I(a, b)
#define PP_CAT_I(a, b) PP_CAT_II(~, a ## b)
#define PP_CAT_II(p, res) res

#define UNIQUE_NAME(base) PP_CAT(base, __COUNTER__)
Run Code Online (Sandbox Code Playgroud)

__COUNTER__传闻有可移植性问题.如果是这样,您可以使用__LINE__,只要您不是每行调用一次宏或在编译单元之间共享名称,您就可以了.


pop*_*cnt 12

将M4添加到您的构建流程中?这种宏语言具有一些有状态功能,可以成功地与CPP宏混合.这可能不是在C环境中生成唯一名称的标准方法,尽管我已经能够以这种方式成功使用它.

根据你提出问题的方式,你可能根本不想要随机BTW.你想要独一无二.

你可以在宏扩展中使用__FILE____LINE__来获得你似乎要去的唯一性...那些元变量在源文件上下文中定义,所以要小心确保你得到你想要的东西(例如,同一行上有多个宏).

  • 这对我不起作用,因为我可以在同一个文件中多次使用宏,稍后在另一个宏中引用它."__ COUNTER __"(我知道它们在一起)可能有效,但我需要知道计数器的当前值而不增加它. (5认同)
  • 还有__COUNTER__宏,它在每次调用时都会生成新的整数,但它是非标准的. (4认同)
  • 哇,现在有了评论格式!无论如何,这真的应该是 COUNTER 前后有两个下划线。 (2认同)

小智 11

使用__COUNTER__(适用于gcc4.8,clang 3.5和Intel icc v13,MSVC 2015)

#define CONCAT_(x,y) x##y
#define CONCAT(x,y) CONCAT_(x,y)
#define uniquename static bool CONCAT(sb_, __COUNTER__) = false
Run Code Online (Sandbox Code Playgroud)

  • 很好,我不知道##。 (2认同)
  • 这不起作用,\ _ _ _ _ COUNTER\_\_ _不会展开.预处理器的输出是:static bool sb\_\_ _ _ COUNTER\_\_ = false; (2认同)
  • 在我添加该评论后,似乎有人编辑了答案。最初的版本直接使用 \_\_COUNTER\__\_ ,但您需要间接使用 CONCAT 宏才能正常工作。 (2认同)

D.S*_*ley 8

在预处理器中生成唯一名称很困难.你可以得到的最接近的是像popcnt所暗示的那样变形__FILE____LINE__进入符号.如果你真的需要生成唯一的全局符号名称,那么我会遵循他的建议,即在你的构建系统中使用类似M4或Perl脚本的东西.

您可能不需要唯一的名称.如果您的宏可以强加一个新范围,那么您可以使用相同的名称,因为它只会影响其他定义.我通常遵循在do { ... } while (0)循环中包装宏的常见建议.这仅适用于作为语句的宏 - 而不是表达式.宏可以使用输出参数更新变量.例如:

#define CALC_TIME_SINCE(t0, OUT) do { \
     std::time_t _tNow = std::time(NULL); \
     (OUT) = _tNow - (t0); \
} while (0)
Run Code Online (Sandbox Code Playgroud)

如果你遵循一些规则,你通常很安全:

  1. 对宏中定义的符号使用前导下划线或类似的命名约定.这将防止与使用相同符号的参数相关的问题发生.
  2. 仅使用输入参数一次,并始终用括号括起来.这是使宏使用表达式作为输入的唯一方法.
  3. 使用该do { ... } while (0)成语确保宏仅用作语句并避免其他文本替换问题.

  • 使用前导下划线并不是一个好主意,因为这样生成的名称可能与实现保留名称冲突,并且无论如何都是自己保留的. (2认同)