C预处理器:__ COUNTER__的自己实现

时间:2014-03-27 16:26:13

标签: c macros c-preprocessor

我目前正在使用C库代码中的__COUNTER__宏来生成唯一的整数标识符。它工作得很好,但我看到两个问题:

  • 它不是任何C或C ++标准的一部分。
  • 使用__COUNTER__的独立代码可能会感到困惑。

因此,我希望自己实现等同于__COUNTER__

我知道的替代品,但想要使用:

  • __LINE__(因为每行多个宏不会获得唯一ID)
  • BOOST_PP_COUNTER(因为我不想要boost依赖项)

BOOST_PP_COUNTER证明可以做到这一点,即使other答案声称这是不可能的。

本质上,我正在寻找一个头文件“mycounter.h”,这样

#include "mycounter.h"

__MYCOUNTER__
__MYCOUNTER__ __MYCOUNTER__
__MYCOUNTER__

将由gcc -E预处理

(...)

0
1 2
3

不使用内置__COUNTER__

注意:此前,此问题被标记为this的副本,该问题涉及使用__COUNTER__而不是避免使用它。

3 个答案:

答案 0 :(得分:3)

您无法直接实施__COUNTER__。预处理器纯粹是功能性的 - 没有状态变化。在这样的系统中,隐藏的计数器本身是不可能的。 (BOOST_PP_COUNTER

}那就是说,实施很棒,无论如何你应该读它。)

您可以做的是重构您的元程序,以便计数器可以通过纯函数应用于输入数据。例如使用好的'Order

#include

(递减列表,将子列表元素保留在原来的位置,并用__LINE__替换非列表元素 - 用递增的计数器变量替换)

我假设您实际上并不想简单地在程序顶层删除#include <order/interpreter.h> #define ORDER_PP_DEF_8map_count \ ORDER_PP_FN(8fn(8L, 8rec_mc(8L, 8nil, 0))) #define ORDER_PP_DEF_8rec_mc \ ORDER_PP_FN(8fn(8L, 8R, 8C, \ 8if(8is_nil(8L), \ 8R, \ 8let((8H, 8seq_head(8L)) \ (8T, 8seq_tail(8L)) \ (8D, 8plus(8C, 1)), \ 8if(8is_seq(8H), \ 8rec_mc(8T, 8seq_append(8R, 8seq_take(1, 8L)), 8C), \ 8rec_mc(8T, 8seq_append(8R, 8seq(8C)), 8D) ))))) ORDER_PP ( 8map_count(8seq( 8seq(8(A)), 8true, 8seq(8(C)), 8true, 8true )) //((A))(0)((C))(1)(2) ) 值,因此如果您可以将需要编码的代码放在一个包装宏中的8false值内然后,您可以将列表提供给类似于示例的纯函数。

当然,能够表达此类代码的元编程库将比__COUNTER__ 显着更不便于携带和维护。 __COUNTER__由英特尔,GCC,Clang和MSVC提供支持。 (不是每个人,例如__COUNTER__都没有它,但是有人甚至没有使用它吗?)可以说,如果你在实际代码中展示了这个特性,那么标准化委员会就会{{1} } 应该成为下一个C标准的一部分。

答案 1 :(得分:2)

你混淆了两件事:

1 - 处理#define#include之类的东西的预处理器。它仅作为文本(意思是字符序列)级别起作用,并且具有很少的计算能力。它非常有限,无法实现__COUNTER__。预处理器工作仅包括宏扩展和文件替换。关键是它在之前发生编译甚至开始。

2 - C ++语言,特别是模板(元)编程语言,可用于在编译阶段计算内容。它确实是完整的,但正如我已经说过预处理后的编译开始。

所以你要问的是在标准C或C ++中不可行。为了解决这个问题,boost实现了自己的预处理器,它不符合标准并具有更多的计算能力。特别是可以使用它来构建__counter__的类似物。

答案 2 :(得分:-1)

This small header of mine包含一个自己的C预处理器计数器实现(它使用稍微不同的语法)。