tags:

views:

44

answers:

3

The following (test with gcc -E blah.c):

#define UNUSED(type) type UNUSED_ ## __COUNTER__
UNUSED(char const *)
UNUSED(int)

Generates:

char const * UNUSED__COUNTER__
int UNUSED__COUNTER__

I'm expecting:

char const * UNUSED0
int UNUSED1

I've tried calling another macro, wrapping the arguments in brackets to no avail. If I don't paste the tokens it seems to work fine. The documentation specifically mentions the use of __COUNTER__ in token pasting.

What am I doing wrong?

A: 

I believe you must "double expand" it:

#define STR(x)    #x
#define UNUSED(type) type UNUSED_ ## STR(__COUNTER__)
UNUSED(char const *) 
UNUSED(int) 
James Curran
No luck with this: `char const * UNUSED_STR(0)` and `int UNUSED_STR(1)`
Matt Joiner
Is space after UNUSED_ the issue?
Chubsdad
You surely didn't mean to stringify, did you? If this worked at all, it would produce things like `char const * UNUSED"0"`...
Zack
+1  A: 

__COUNTER__ was only introduced in GCC 4.3 - if you happen to use an earlier version, the macro is simply not defined. In that case Boost.PPs BOOST_PP_COUNTER macro might be worth looking into.

On newer GCC versions you still need a different approach to concatenation, as ## prevents its arguments from expanding. Thus you have to expand them first before using ##:

#define CAT(a, b) CAT_I(a, b)
#define CAT_I(a, b) CAT_II(a ## b)
#define CAT_II(x) x
#define UNUSED(type) type CAT(UNUSED_, __COUNTER__)

If you're already using Boost, BOOST_PP_CAT() gives you the same functionality.

Georg Fritzsche
Sorry the C++ tag was incorrect, SO changes cpp to c++... apparently someone hasn't heard of the C preprocessor
Matt Joiner
@Matt: The answer is the same for C and C++, even Boost.PP works with both.
Georg Fritzsche
I mean that C++isms such as Boost are not useful here. But thanks for the info.
Matt Joiner
+1  A: 

Experimenting with gcc 4.4, this works:

#define UNUSED(type) UNUSED_(type, __COUNTER__)
#define UNUSED_(type, counter) UNUSED__(type, counter)
#define UNUSED__(type, counter) type UNUSED_ ## counter
UNUSED(char const *)
UNUSED(int)

But it doesn't work if I take out even one level of intermediates.

Zack