126 lines
5.1 KiB
HTML
126 lines
5.1 KiB
HTML
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
|
<link rel="stylesheet" type="text/css" href="../../../boost.css">
|
|
<title>Boost.Preprocessor - Widely known problems with the C preprocessor</title>
|
|
</head>
|
|
<body link="#0000ff" vlink="#800080">
|
|
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
|
"header">
|
|
<tr>
|
|
<td valign="top" width="300">
|
|
<h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
|
|
</td>
|
|
<td valign="top">
|
|
<h1 align="center">Boost.Preprocessor</h1>
|
|
<h2 align="center">Widely known problems with the C preprocessor</h2>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<hr>
|
|
|
|
<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>
|
|
|
|
<pre>#define MACRO ...
|
|
// Use MACRO
|
|
#undef MACRO
|
|
</pre>
|
|
|
|
<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>
|
|
|
|
<pre>#define UMP_MACRO
|
|
// Use UMP_MACRO
|
|
</pre>
|
|
|
|
|
|
<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="bibliography.htm#[McConnell]">[McConnell]</A>.</EM></B></P>
|
|
<HR>
|
|
|
|
<P><B>PROBLEM:</B> "I'd
|
|
like to see Cpp abolished." - Bjarne Stroustrup in <A href="bibliography.htm#[Stroustrup]">[Stroustrup]</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="bibliography.htm#[Czarnecki]">[Czarnecki]</A>.</B></EM></P>
|
|
<hr>
|
|
<p>Revised
|
|
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
</p>
|
|
<p><i>© Copyright <a href="http://www.housemarque.com">Housemarque Oy</a> 2002</i></p>
|
|
|
|
<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>
|
|
</body>
|
|
</html>
|