[comp.lang.c++] Token pasting

jamshid@emx.utexas.edu (Jamshid Afshar) (07/01/91)

Hi, I just thought I'd share something in the hopes others won't also
waste a couple of hours discovering non-intuitive (but I'm sure
necessary) ANSI rules about macro expansion and token pasting. First,
I'm assuming you know about the token-pasting operator "##":
   x##y -> xy

I am working on some simple list templates (okay, macros).  The macro
DEFINE_LIST(TYPE) will expand to the LIST and ITERATOR class
definitions: TYPEList and TYPEListIter.  LIST(TYPE) will expand to
"TYPEList" and ITERATOR(TYPE) will expand to "TYPEListIter" so client
code will look like:

...
DEFINE_LIST(char);
...
void foo()
{
      // the_list is a list of char (type is 'charList')
   LIST(char) the_list;
      // the_iter is an iterator over the_list (type is 'charListIter')
   ITERATOR(char) the_iter(the_list);
   ...
}

I originally used the following definitions of LIST and ITERATOR:

#define LIST(ITEM_TYPE)       ITEM_TYPE ## List
#define ITERATOR(ITEM_TYPE)   LIST(ITEM_TYPE) ## Iter

I got compilation errors from BC++, so I tried running a 'cpp' which
Borland provides as part of their package (the compiler has a
built-in preprocessor, so it doesn't actually use this cpp).  My code
would compile fine after going through the separate cpp.  Anyway, it
turns out the the compiler is ANSI, but the cpp Borland provides is
not (BTW, neither is TI's cpp).  The ITERATOR(ITEM_TYPE) macro does
not expand into 'ITEM_TYPE ## List ## Iter' as you might think
because of ANSI macro expansion and token pasting rules -- an extra
level of indirection is required.

The following four macros accomplish what I want done.  BTW, I
discovered this by looking at Borland's <generic.h>, which I assume 
is modeled after something that comes with AT&T CC or g++.

#define _PASTE(x,y) x##y
#define PASTE(x,y) _PASTE(x,y)

   /* Is there any reason I should also use PASTE here? */
#define LIST(ITEM_TYPE) ITEM_TYPE##List   

#define ITERATOR(ITEM_TYPE) PASTE(LIST(ITEM_TYPE),Iter)

That's all, just FYI.  If anybody can explain in simple terms why the
extra level of indirection is required, I would appreciate it.


Jamshid Afshar
jamshid@emx.utexas.edu