5

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.

Community
  • 1
  • 1
mic_e
  • 4,684
  • 2
  • 29
  • 44
  • 1
    In some situations `__LINE__` may be a good replacement of `__COUNTER__`. – vharavy Mar 27 '14 at 16:55
  • As I pointed out in the question, `__LINE__` does not suffice for my purposes. – mic_e Mar 27 '14 at 17:44
  • 2
    Study the design of BOOST_PP_COUNTER and reimplement it your own way, but that's going to be harder than just reusing boost::preprocessor. – Jonathan Leffler Mar 27 '14 at 18:31
  • @Hans Passant - it looks like the potential duplicate uses `__COUNTER__` itself. I think mic_e is trying to avoid that because he states "without using the built-in `__COUNTER__`". – jww Mar 27 '14 at 20:25
  • Agreed, this question **IS NOT** a duplicate. – JasonMArcher Mar 28 '14 at 16:58
  • Does this help? [Does C++ support compile-time counters?](http://stackoverflow.com/q/6166337/153285) – Potatoswatter Mar 29 '14 at 07:20
  • @Potatoswatter: I don't think so. While `C++11` is at my full disposal, I need a macro that works as part of an expression, and will also increment the counter on use. I don't think that's possible with your code (but I didn't take the time to fully comprehend it) – mic_e Mar 29 '14 at 15:31

3 Answers3

3

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.

Leushenko
  • 11,633
  • 9
  • 44
  • 84
  • 1
    Macro expansion does not admit state changes or inspection of previous states but the preprocessor is stateful. – Potatoswatter Mar 29 '14 at 07:22
  • I think you made your point for continuing to usse `__COUNTER__`. Also, wow, I didn't even know about Order. – mic_e Mar 29 '14 at 13:49
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.

hivert
  • 10,116
  • 3
  • 27
  • 51
  • 1
    I am fully aware of the difference between the CPP and template metaprogramming. I have re-titled the question to remove the confusion. As I mentioned in my question, and is discussed here: http://stackoverflow.com/a/3136798/1347646, the CPP is turing-complete, so it should definitely be able to do this. Boost even implements it (with the standard CPP), and thus proofs that it is doable. – mic_e Mar 27 '14 at 16:55
  • I'm sorry but the way you put it your question is too vague. What do you want to generate ? Different strings ? Different variables ? As I explained you can't generate macros. – hivert Mar 27 '14 at 17:01
  • Thanks, I've updated the question to hopefully be more clear now. – mic_e Mar 27 '14 at 17:14
  • Note that the C and C++ preprocessor can perform arithmetic on constant integer expressions and has conditional directives. It is inaccurate to say that *The preprocessor work consists only of macro expansion and file inclusion.* – Filipe Gonçalves Mar 28 '14 at 17:08
  • @mic_e I think you missed the part about "Note that an external build script is needed to feed the preprocessor's output back into its input, so the preprocessor in and of itself isn't Turing complete." It sounds like Boost does something similar, so your options are (1) use boost, or (2) reimplement it yourself. – Kevin Mar 28 '14 at 23:27
0

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

madmurphy
  • 737
  • 5
  • 11
  • 1
    I voted your answer up because it was at -1 and nobody had commented the reason for the downvote. – fuzzyTew Mar 22 '20 at 23:49
  • @madmurphy as I understand it, it is impossible to implement a counter with this library, since you have to pass to the macro the current position (i. e. from the example: `ZEN_COUNTER_NEXT(SECOND_VALUE)`), so you have to know that you are currently in the `SECOND_VALUE`, while the point of `__COUNTER__` is not to know it. If you can show an example of use of the library without the current counter, then I will upvote. – LoPiTaL Sep 23 '20 at 11:42