简体   繁体   English

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

[英]C Preprocessor: Own implementation for __COUNTER__

I'm currently using the __COUNTER__ macro in my C library code to generate unique integer identifiers. 我当前在C库代码中使用__COUNTER__宏来生成唯一的整数标识符。 It works nicely, but I see two issues: 效果很好,但是我看到两个问题:

  • It's not part of any C or C++ standard. 它不是任何C或C ++标准的一部分。
  • Independent code that also uses __COUNTER__ might get confused. 也使用__COUNTER__独立代码可能会造成混淆。

I thus wish to implement an equivalent to __COUNTER__ myself. 因此,我希望自己实现与__COUNTER__等效的__COUNTER__

Alternatives that I'm aware of, but do not want to use: 我知道但希望使用的替代方法:

  • __LINE__ (because multiple macros per line wouldn't get unique ids) __LINE__ (因为每行多个宏不会获得唯一的ID)
  • BOOST_PP_COUNTER (because I don't want a boost dependency) BOOST_PP_COUNTER (因为我不想boost依赖)

BOOST_PP_COUNTER proves that this can be done, even though other answers claim it is impossible. BOOST_PP_COUNTER证明可以做到这一点,即使其他答案认为这是不可能的。

In essence, I'm looking for a header file "mycounter.h", such that 本质上,我正在寻找头文件“ mycounter.h”,这样

#include "mycounter.h"

__MYCOUNTER__
__MYCOUNTER__ __MYCOUNTER__
__MYCOUNTER__

will be preprocessed by gcc -E to 将由gcc -E预处理为

(...)

0
1 2
3

without using the built-in __COUNTER__ . 而不使用内置的__COUNTER__

Note: Earlier, this question was marked as a duplicate of this , which deals with using __COUNTER__ rather than avoiding it. 注意:之前,此问题被标记为this的重复,它使用__COUNTER__而不是避免使用。

You can't implement __COUNTER__ directly. 您不能直接实现__COUNTER__ The preprocessor is purely functional - no state changes. 预处理器纯粹是功能性的-状态不变。 A hidden counter is inherently impossible in such a system. 在这种系统中,隐藏计数器本质上是不可能的。 ( BOOST_PP_COUNTER does not prove what you want can be done - it relies on #include and is therefore one-per-line only - may as well use __LINE__ . That said, the implementation is brilliant, you should read it anyway.) BOOST_PP_COUNTER 不能证明您要完成的工作-它依赖于#include ,因此仅一行执行-最好使用__LINE__ 。也就是说,实现非常出色,无论如何都应该阅读它。)

What you can do is refactor your metaprogram so that the counter could be applied to the input data by a pure function. 您可以做的是重构您的元程序,以便可以通过纯函数将计数器应用于输入数据。 eg using good ol' Order : 例如,使用良好的命令

#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)
)

(recurses down the list, leaving sublist elements where they are and replacing non-list elements - represented by 8false - with an incrementing counter variable) (沿列表递归,将子列表元素留在原处,并用递增计数器变量替换非列表元素(由8false表示))

I assume you don't actually want to simply drop __COUNTER__ values at the program toplevel, so if you can place the code into which you need to weave __COUNTER__ values inside a wrapper macro that splits it into some kind of sequence or list, you can then feed the list to a pure function similar to the example. 我假设您实际上并不想简单地在程序顶层删除__COUNTER__值,因此如果您可以将需要编织__COUNTER__值的代码放入包装宏中,该宏会将其拆分为某种序列或列表,则可以然后将列表提供给与示例类似的纯函数。

Of course a metaprogramming library capable of expressing such code is going to be significantly less portable and maintainable than __COUNTER__ anyway. 当然,与__COUNTER__相比,能够表达这种代码的元编程库的可移植性和可维护性将大大降低。 __COUNTER__ is supported by Intel, GCC, Clang and MSVC. __COUNTER__受Intel,GCC,Clang和MSVC支持。 (not everyone, eg pcc doesn't have it, but does anyone even use that?) Arguably if you demonstrate the feature in use in real code, it makes a stronger case to the standardisation committee that __COUNTER__ should become part of the next C standard. (不是所有人,例如pcc都没有,但是有人甚至使用它吗?)可以说,如果您在实际代码中演示了正在使用的功能,则对于标准化委员会来说, __COUNTER__ 应该成为下一个C的一部分更有力。标准。

You are confusing two different things: 您在混淆两件事:

1 - the preprocessor which handles #define and #include like stuff. 1-处理#define#include类的预处理器。 It does only works as the text (meaning character sequences) level and has very few computing capabilities. 它仅在文本(含义是字符序列)级别上起作用,并且具有很少的计算能力。 It is so limited that it cannot implement __COUNTER__ . 它是如此有限,以致于无法实现__COUNTER__ The preprocessor work consist only in macro expansion and file replacement. 预处理程序仅包括宏扩展和文件替换。 The crucial point it that it occur before the compilation even start. 至关重要的一点是,它甚至在编译开始之前就已发生。

2 - the C++ language and in particular the template (meta)programming language which can be used to compute stuff during the compilation phase. 2-C ++语言,尤其是模板(元)编程语言,可用于在编译阶段计算内容。 It is indeed turing complete but as I already said compilation start after preprocessing. 它确实已经完成,但是正如我已经说过的,编译是在预处理之后开始的。

So what you are asking is not doable in standard C or C++. 因此,您要问的是在标准C或C ++中不可行。 To solve this problem boost implement its own preprocessor which is not standard compliant and has much more computing capabilities. 为了解决这个问题, boost实现了自己的不符合标准且具有更多计算能力的预处理器。 In particular it is possible to use build an analogue to __counter__ with it. 特别地,可以使用__counter__建立__counter__的类似物。

我的这个小标头包含一个自己的C预处理程序计数器实现(它使用略有不同的语法)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM