Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!usc!cs.utexas.edu!ut-emx!emx.utexas.edu From: jamshid@emx.utexas.edu (Jamshid Afshar) Newsgroups: comp.lang.c++ Subject: Token pasting (x##y) suprise Keywords: operator ##, preprocessor Message-ID: <51504@ut-emx.uucp> Date: 1 Jul 91 02:01:20 GMT Sender: jamshid@ut-emx.uucp Organization: The University of Texas at Austin; Austin, Texas Lines: 58 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 , 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