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:
__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.
(C++11) The predefined identifier __func__ is implicitly defined as a string that contains the unqualified and unadorned name of the enclosing function. __func__ is mandated by the C++ standard and is not a Microsoft extension.
The #ifdef is one of the widely used directives in C. It allows conditional compilations. During the compilation process, the preprocessor is supposed to determine if any provided macros exist before we include any subsequent code.
We can consider a preprocessor as a compilation process, which runs when the developer runs the program. It is a pre-process of execution of a program using c/c++ language. To initialize a process of preprocessor commands, it's mandated to define with a hash symbol (#).
The #ifdef identifier statement is equivalent to #if 1 when identifier has been defined. It's equivalent to #if 0 when identifier hasn't been defined, or has been undefined by the #undef directive.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With