5

I am doing some template meta programming, mostly just writing my own compile time list, but I also have some preprocessor magic which I want to use to make things easier if possible.

What I am trying to do is create a compile time list of functors. That part is done, but the macros to ease creation (and add to the list) are not.

An example in brief:

template<typename Functor, typename Tail>
struct node {
    typedef Functor head;
    typedef Tail tail;
};


template <typename Functor, typename Tail>
struct push_back {
    typedef node<Functor, Tail> list;
};

struct unit0 {};

#define AUTO_FUNCTION(name) struct test_functor_##name {            \
    static void run_test();                                         \
};                                                                  \
typedef push_back<                                                  \
            test_functor_##name,                                    \
            CONCAT(unit, PP_DEC(__COUNTER__))                       \
        >::list CONCAT(unit, __COUNTER__);                          \
void test_functor_##name::run_test()


AUTO_FUNCTION(hello) {
    ...
}

Now, this works because I have created a large set of preprocessor macros for PP_DEC, ie:

#define PP_DEC(x) PP_DEC_I(x)
#define PP_DEC_I(x) PP_DEC_ ## x
#define PP_DEC_1 0
#define PP_DEC_2 1
...
#define PP_DEC_N N

That's the part I really want to avoid and the reason I am asking this question. Does anyone have a suggestion on how I can use COUNTER without increasing its value, or some other way I can accomplish a counting pattern similar to:

 0 1
 1 2
 2 3
 ...

Suggestions that change the semantics of push_back, etc. are of course also welcome :).

PS. This is not meant for production, only for fun. So GCC specific extensions are welcomed.

PPS. I am trying to avoid external dependencies, such as boost, as I want to understand everything I am doing (the whole point of this project).

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Mic
  • 6,741
  • 3
  • 24
  • 25
  • `__COUNTER__` is a Microsoft language extension, not standard C++ – Cheers and hth. - Alf Jan 18 '11 at 01:18
  • @Alf P. Steinbach - I know. It does exist in GCC 4.3 and clang though, and since I really don't mind using compiler specific extensions for this (since it is only for fun), `__COUNTER__` was used. Any other suggestion which accomplishes something similar without `__COUNTER__` is of course welcome. – Mic Jan 18 '11 at 01:21
  • I am having a similar issue - did you manage to solve this? Thanks. =) – Andreas Grapentin Dec 29 '14 at 11:25

1 Answers1

13

You can "fix" __COUNTER__ value by using an extra macro:

#define MY_MACRO MY_MACRO_COUNTED(__COUNTER__)

#define MY_MACRO_COUNTED(counter) counter + counter
Grigory Entin
  • 1,617
  • 18
  • 20
  • Is it really working? I tested and I'm getting different values when I call `MY_MACRO` each time. – Phillip Aug 15 '18 at 14:48
  • 1
    @Phillip You should get different values every time you call MY_MACRO. The thing is that `counter` value _inside_ the macro should be the same, even if it's used multiple times. I.e. every time the macro gets expanded, `__COUNTER__` will be different, so you'll get different results. The "fix" just addresses the usage of `__COUNTER__` during macro expansion - without it `__COUNTER__` value would be different every time it's referenced in the macro body. – Grigory Entin Aug 15 '18 at 14:51
  • Could you include an example of how to use this twice inside a macro? – Tor Klingberg Feb 26 '20 at 17:45
  • @TorKlingberg It's used twice in `#define MY_MACRO_COUNTED(counter) counter + counter` in the above example - so (I guess) every invocation of `MY_MACRO` should effectively return `2 * (initial value of) __COUNTER__`, as opposed to `2 * (initial value of) __COUNTER__ + 1`, if `__COUNTER__` is used directly as in `#define MY_MACRO __COUNTER__ + __COUNTER__`. – Grigory Entin Feb 26 '20 at 19:28