2001-11-25 18:32:11 +00:00
|
|
|
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
|
|
|
|
<HTML><HEAD><TITLE>Boost PREPROCESSOR library</TITLE>
|
|
|
|
|
<BODY bgcolor="#ffffff">
|
|
|
|
|
<a href="index.htm"><IMG height=86
|
|
|
|
|
alt="c++boost.gif (8819 bytes)"
|
|
|
|
|
src="../../../c++boost.gif"
|
|
|
|
|
width=277 align=center></a>
|
|
|
|
|
<hr>
|
|
|
|
|
|
|
|
|
|
<h1>Boost PREPROCESSOR library: Widely known problems with the C preprocessor</h1>
|
|
|
|
|
|
|
|
|
|
<p>
|
|
|
|
|
|
|
|
|
|
Preprocessor metaprogramming is subject to heated discussions. Part of this is caused by
|
|
|
|
|
bad experiences with dangerous techniques, such as defining inline functions using macros. As a rule
|
|
|
|
|
of thumb, if you can find a clean and
|
|
|
|
|
manageable way to do something without using the preprocessor, then
|
|
|
|
|
you should do it that way.</p>
|
|
|
|
|
|
|
|
|
|
<p>Let's survey some of the widely known problems with the preprocessor in a problem/solution
|
|
|
|
|
format.</p>
|
|
|
|
|
<HR>
|
|
|
|
|
|
|
|
|
|
<p><B>PROBLEM:</B> Preprocessor does not
|
|
|
|
|
respect scope, therefore macros can accidentally and sometimes silently replace
|
|
|
|
|
code.</p>
|
|
|
|
|
|
|
|
|
|
<p><B>SOLUTION A:</B> Use all caps identifiers
|
|
|
|
|
for macros and only macros. This practically eliminates the possibility that a
|
|
|
|
|
macro might replace other kind of code accidentally.</p>
|
|
|
|
|
|
|
|
|
|
<p><B>SOLUTION B:</B> Use the Local Macro
|
|
|
|
|
idiom:</p>
|
|
|
|
|
|
|
|
|
|
<blockquote><pre>#define MACRO ...
|
|
|
|
|
// Use MACRO
|
|
|
|
|
#undef MACRO
|
|
|
|
|
</pre></blockquote>
|
|
|
|
|
|
|
|
|
|
<p>This makes sure that a macro can not accidentally
|
|
|
|
|
replace code outside of the scope of the local macro.</p>
|
|
|
|
|
<P>A problem with this solution is that the #undef can not be automated and may be
|
|
|
|
|
forgotten. Experienced programmers generally write the #undef either immediately
|
|
|
|
|
before (in time) or immediately after writing the macro definition.</P>
|
|
|
|
|
<P><B>SOLUTION C:</B> Use the Unique Macro Prefix idiom:</P>
|
|
|
|
|
|
|
|
|
|
<blockquote><pre>#define UMP_MACRO
|
|
|
|
|
// Use UMP_MACRO
|
|
|
|
|
</pre></blockquote>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<P>This makes accidental substitution and collisions highly
|
|
|
|
|
unlikely. Problems with this solution:</P>
|
|
|
|
|
<UL>
|
|
|
|
|
<LI>
|
|
|
|
|
There can still be naming collisions inside a large project.
|
|
|
|
|
<LI>
|
|
|
|
|
Macros still pollute the global namespace. </LI></UL>
|
|
|
|
|
<P><EM><B>By combining all solutions, whenever
|
|
|
|
|
possible, the scope problem can be largely avoided.</B></EM></P>
|
|
|
|
|
<HR>
|
|
|
|
|
|
|
|
|
|
<P><B>PROBLEM:</B> Preprocessor code is difficult to read.
|
|
|
|
|
It requires understanding the basic process of how
|
|
|
|
|
the preprocessor recursively expands macros, finding the macro definition and mentally
|
|
|
|
|
substituting the parameters of the macro. </P>
|
|
|
|
|
<P><B>SOLUTION:</B> Any kind of programming requires basic understanding
|
|
|
|
|
of how the code is executed. Any parameterization technique, including simple
|
|
|
|
|
functions and templates requires finding the definition and mentally substituting
|
|
|
|
|
parameters. </P>
|
|
|
|
|
<P>However, it is good to know a few techniques:</P>
|
|
|
|
|
<UL>
|
|
|
|
|
<LI>
|
|
|
|
|
By using as many Local Macros as reasonable, the bulk of the searching
|
|
|
|
|
process can be eliminated.
|
|
|
|
|
<LI>
|
|
|
|
|
Code browsers and text search tools make it easier to find the
|
|
|
|
|
definitions.
|
|
|
|
|
<LI>
|
|
|
|
|
The compiler can be used for generating the preprocessed source code in
|
|
|
|
|
order to look for bugs.
|
|
|
|
|
<LI>
|
|
|
|
|
Before turning something into a preprocessor metaprogram, first
|
|
|
|
|
implement a small scale version of it without preprocessor. Then work
|
|
|
|
|
bottom->up replacing hand written constructs by using preprocessor. This
|
|
|
|
|
way you can test the code incrementally. Experienced programmers often skip
|
|
|
|
|
many stages, but if something proves too complex to write directly, it is
|
|
|
|
|
always possible to fall back to incremental methods.
|
|
|
|
|
<LI>
|
|
|
|
|
If you insert a special symbol into the preprocessor code in places where
|
|
|
|
|
there should be a line break, you can make code readable after preprocessing
|
|
|
|
|
simply by using a search and replace tool. </LI></UL>
|
|
|
|
|
<P><B><EM> An especially important thing to remember is to limit the use of preprocessor
|
|
|
|
|
to the structured, well understood and safe methods. Structure helps to understand
|
|
|
|
|
complex systems <A href="references.htm#[4]">[4]</A>.</EM></B></P>
|
|
|
|
|
<HR>
|
|
|
|
|
|
|
|
|
|
<P><B>PROBLEM:</B> "I'd
|
|
|
|
|
like to see Cpp abolished." - Bjarne Stroustrup in <A href="references.htm#[1]">[1]</A></P>
|
|
|
|
|
<P><B>SOLUTION:</B> The C preprocessor will be here for a
|
|
|
|
|
long time.</P>
|
|
|
|
|
<P><EM><B>In practice, preprocessor metaprogramming is far simpler and more portable
|
|
|
|
|
than template metaprogramming <A href="references.htm#[2]">[2]</A>.</B></EM></P>
|
|
|
|
|
<hr>
|
2001-12-03 21:20:27 +00:00
|
|
|
|
<P><EFBFBD> Copyright Housemarque Oy 2001</P>
|
2001-11-25 18:32:11 +00:00
|
|
|
|
<p>Permission to copy, use, modify, sell and distribute this document is granted
|
|
|
|
|
provided this copyright notice appears in all copies. This document is provided
|
|
|
|
|
"as is" without express or implied warranty, and with no claim as to its suitability
|
|
|
|
|
for any purpose. </p>
|
|
|
|
|
<p>Updated: <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan --><!--webbot bot="Timestamp" endspan i-checksum="15246" --></p>
|
|
|
|
|
<p></p>
|
|
|
|
|
|
|
|
|
|
</BODY></HTML>
|