Demystify C++ Metaprograms using Emacs

The problem of macro expansion has resurfaced in modern C++ due to limitations with meta-programming in C++.  Although frowned upon in general use because of the issues inherent to macro hygene and type safety, C pre-processor macros are seeing a resurgance in their popularity by way of  C++ meta programming where  they are used to compensate for the inherent limitations of template parameterization (STL). Pre-processor macros allow arbitrary textual transformations, hence may be used, in a very limited way, to similar effect as Lisp macros when these are used in combination with STL templates.

Besides problems with type safety and macro hygiene, pre-processor macros suffer the additional complication that, when they are evaluated, neither the facilities of the C language nor the facilities of the C++ language are available. Typically, transformations effected by pre-processor macros obfuscate for the reader of the code what the compiler eventually processes into object code.

STL template meta programs already generate lengthy error messages that are difficult to read. Obfuscating the code with macros that hide what lies beneath can make the situation truly untenable. Yet, pre-processor macro expansion is trivial. Stereotypically the -E option can be used to elicit uncompiled, macro expanded code from the compiler. The trouble is, like STL template errors, the output from the preprocessor can be genuinely painful. Take the below simple program as an example:

Simple Hello World

The pre-processor output is too lengthy to reproduce here – in excess of 40,000 lines of code:

Pre-Processor Output

Happy navigating! Yet only two header files were included in this trivial example.

Let us look at something more representative: the BOOST auto test case macro:

(This example is taken from http://www.alittlemadness.com/2009/03/31/c-unit-testing-with-boosttest/)

BOOST Test Case

Now we are up to some 70 thousand lines.

BOOST Test Case Macro Expansion

Lets check how readable the output is. We’ll just grab the last few lines.

Macro Preprocessor Readability

I don’t know about you, but I don’t want to have to do the mental code walk. Emacs actually used to have sensible C macro pre-processor support, but this appears to have fallen in disrepair with C++. Addressing this issue for C++ is the aim of the Emacs Demystify plugin.

When in C++ mode, the plugin in invoked by M-x cpp-demystify. Demistify will open a temporary buffer using the original buffer name and wrap the name in what is termed earmuffs in Lisp. So if the C++ buffer is universe.cpp, the the macro expansion will be *universe.cpp*. This buffer will not be associated with a file name so should not be edited. An example is shown below. Include directives will be elided. Only expanded source code is shown.  The temporary buffer will automatically be placed into C++ mode. If you edit the original and re-expand the macros with a renewed M-x cpp-demystify, then the existing buffer will be updated.

Demystify

The source code for the Emacs Demystify plugin may be found at https://github.com/chriskmanx/demystifycpp.

 

 

 

 

 

4 responses to “Demystify C++ Metaprograms using Emacs

  1. Rob G

    Seems to me this has little to do with metaprograms, much to do with demystifying preprocessor abuse.

    • Thank you Rob for your feedback. I guess my comment would be that what you hold to be pre-processor abuse is fairly well standard in BOOST which is a reasonably well respected C++ library. Perhaps the authors of, for example BOOST test, arrived at a different conclusion. I have seen a few advanced meta-programmming projects in C++ arrive at the same point: where templates won’t do and developers resort to mixing in preprocessor macros. I don’t claim to be a friend of this technique, but find myself having to make sense of code written in this style. End of apologetics…

  2. Nicholas

    This would also be helpful for Google Test, a unit testing framework that makes extensive use of macros.

    I think Google Test works well, but it’s often difficult to understand compiler error messages when they come from “expanded” source code.

    • There is also the issue that source level debugging is impossible where the code only exists between the pre-processor and the compiler. This I’ve used this technique to compile the expanded source code instead, and then source-level-debug the expanded source code.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s