Click here to Skip to main content
Click here to Skip to main content

Cool Techniques - Metamacros

, 1 Dec 1999
Rate this:
Please Sign up or sign in to vote.
A technique to allow macros to call other macros
<!-- Article Starts -->

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

Share

About the Author

Thales P. Carvalho

United States United States
No Biography provided

Comments and Discussions

 
GeneralActually it's #define _STR_WEEKDAY( Name ) # Name, Pinmemberpg--az16-May-07 11:57 
GeneralSmall bug PinsussIngo K. hunsinger11-Apr-00 1:39 
GeneralRe: Small bug PinmemberJohn Bates11-Feb-02 15:23 
GeneralNeat PinsussRob Deary20-Mar-00 8:43 
GeneralRe: Neat PinmemberAnonymous14-Jun-02 15:04 

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.

| Advertise | Privacy | Mobile
Web03 | 2.8.141022.2 | Last Updated 2 Dec 1999
Article Copyright 1999 by Thales P. Carvalho
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid