Click here to Skip to main content
Licence 
First Posted 1 Dec 1999
Views 45,200
Bookmarked 16 times

Cool Techniques - Metamacros

By | 1 Dec 1999 | Article
A technique to allow macros to call other macros

A cool technique I used in my TCX Unit Conversion Library is what I call "metamacros".

Well, anyone knows that we can not invoke preprocessor directives from preprocessor macros definitions, and as likely it might sound, a metamacro has really nothing to do with this kind of stuff - sorry if I made anyone of you, even for a second, believe I had found a way to fool Santa Claus nonexistence -. A metamacro is simply and basically a macro that accepts another macro as its parameter and invokes that macro within it. It might sound obvious, but there're still plenty room for cool tricks.

For example, the following is a metamacro for the days of the week.

   #define _WEEKDAYS_METADEFS( _m )\
      _m( Sunday )\
      _m( Monday )\
      _m( Tuesday )\
      _m( Wednesday )\
      _m( Thursday )\
      _m( Friday )\
      _m( Saturday )

Now, lets use this metamacro to expand an enum with indexes for the days of the week. All I have to do is:

   #define _ENUM_WEEKDAY( Name ) eWd_##Name,

   enum
   {
      _WEEKDAYS_METADEFS( _ENUM_WEEKDAY )
   };

The preprocessor will create all the eWd_Sunday, eWd_Monday, etc, for me. But, there's more. Let's say now that I want to define a struct with bitfield flags for the days of the week. I can use the metamacro as follow:

   #define _BITFIELD_WEEKDAY( Name )   bool f##Name: 1;

   struct WEEKDAYS_BITFIELDS
   {
      _WEEKDAYS_METADEFS( _BITFIELD_WEEKDAY )
   };

The preprocessor will create all the fSunday, fMonday, etc, flags for me. But WAIT! There's even MORE - did it sound as TV Shopping? -. Let's say now that I want to create a TRACE function to, given a day of the week index (e.g. eWd_Sunday), trace a nice and useful day name (i.e. Sunday), and not the dry literal index. Once again, I can use the metamacro.

   #define _STR_WEEKDAY( Name )	##Name,

   void TraceWeekDayName( int i )
   {
      static const LPCTSTR _aWdNames[ ] =
      {
         _WEEKDAYS_METADEFS(_STR_WEEKDAY)
      };

      if( i < 0 || i < sizeof(_aWdNames)/sizeof(_aWdNames[0]) )
         TRACE( "Invalid" );
      else
         TRACE( _aWdNames[i] );
   }

Do note that, if I have to change the definition of the days of the week, I don't have to make the follow up to every other construction that might be affected by it: the preprocessor does it for me.

Another trick is that I can give the metamacro only the macros prefix, or "macros namespace" (ugh!). Let's show an example, still with the days of the week.

   #define _WEEKDAYS_METADEFS( _m )\
      _m##_WEEKEND( Sunday )\
      _m ( Monday )\
      _m( Tuesday )\
      _m( Wednesday )\
      _m( Thursday )\
      _m( Friday )\
      _m##_WEEKEND ( Saturday )

Now, to expand the same enum for the days of the week I did before, I must do that:

   #define _ENUM_WEEKDAY( Name )          eWd_##Name,
   #define _ENUM_WEEKDAY_WEEKEND( Name )  eWd_##Name,

   enum
   {
      _WEEKDAYS_METADEFS( _ENUM_WEEKDAY )
   };

But, if I want to expand an enum only for the days of the week that are part of the weekend, I can do this:

   #define _ENUM_WEEKDAY2( Name )
   #define _ENUM_WEEKDAY2_WEEKEND( Name )	eWeekend_##Name,

   enum
   {
      _WEEKDAYS_METADEFS( _ENUM_WEEKDAY2 )
   };

And the preprocessor will expand the eWeekend_Sunday and eWeekend_Saturday constants for me. In the TCX Unit Conversion Library I made plenty use of this mechanism. I defined units in a metamacro table that expands several of the concrete structs, tables, constants, and enums that I need. And when I need to change some unit or to include a new one, I can do that in one single place. That's it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Thales P. Carvalho



United States United States

Member



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralActually it's #define _STR_WEEKDAY( Name ) # Name, Pinmemberpg--az11:57 16 May '07  
GeneralSmall bug PinsussIngo K. hunsinger1:39 11 Apr '00  
GeneralRe: Small bug PinmemberJohn Bates15:23 11 Feb '02  
GeneralNeat PinsussRob Deary8:43 20 Mar '00  
GeneralRe: Neat PinmemberAnonymous15:04 14 Jun '02  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web01 | 2.5.120517.1 | Last Updated 2 Dec 1999
Article Copyright 1999 by Thales P. Carvalho
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid