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:
The pre-processor output is too lengthy to reproduce here – in excess of 40,000 lines of code:
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/)
Now we are up to some 70 thousand lines.
Lets check how readable the output is. We’ll just grab the last few lines.
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.
The source code for the Emacs Demystify plugin may be found at https://github.com/chriskmanx/demystifycpp.