C Preprocessor: Own implementation for __COUNTER__

断了今生、忘了曾经 提交于 2020-07-29 06:38:26

问题


I'm currently using the __COUNTER__ macro in my C library code to generate unique integer identifiers. It works nicely, but I see two issues:

  • It's not part of any C or C++ standard.
  • Independent code that also uses __COUNTER__ might get confused.

I thus wish to implement an equivalent to __COUNTER__ myself.

Alternatives that I'm aware of, but do not want to use:

  • __LINE__ (because multiple macros per line wouldn't get unique ids)
  • BOOST_PP_COUNTER (because I don't want a boost dependency)

BOOST_PP_COUNTER proves that this can be done, even though other answers claim it is impossible.

In essence, I'm looking for a header file "mycounter.h", such that

#include "mycounter.h"

__MYCOUNTER__
__MYCOUNTER__ __MYCOUNTER__
__MYCOUNTER__

will be preprocessed by gcc -E to

(...)

0
1 2
3

without using the built-in __COUNTER__.

Note: Earlier, this question was marked as a duplicate of this, which deals with using __COUNTER__ rather than avoiding it.


回答1:


You can't implement __COUNTER__ directly. 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.)

What you can do is refactor your metaprogram so that the counter could be applied to the input data by a pure function. e.g. 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)

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.

Of course a metaprogramming library capable of expressing such code is going to be significantly less portable and maintainable than __COUNTER__ anyway. __COUNTER__ is supported by Intel, GCC, Clang and MSVC. (not everyone, e.g. 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.




回答2:


You are confusing two different things:

1 - the preprocessor which handles#define and #include like stuff. 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__. 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. 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++. To solve this problem boost implement its own preprocessor which is not standard compliant and has much more computing capabilities. In particular it is possible to use build an analogue to __counter__ with it.




回答3:


This small header of mine contains an own implementation of a C preprocessor counter (it uses a slightly different syntax).



来源:https://stackoverflow.com/questions/22693565/c-preprocessor-own-implementation-for-counter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!