preprocessor/doc/known_problems_with_cpp.htm
Vesa Karvonen ab81a9c869 boost.css
[SVN r13956]
2002-05-16 22:17:39 +00:00

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>&nbsp;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&nbsp;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> &nbsp;Preprocessor code is difficult to read.
It requires understanding the basic process of how
the&nbsp;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&nbsp;preprocessor metaprogram, first
implement a small scale version of it without preprocessor. Then work
bottom-&gt;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&nbsp;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&nbsp;<A href="bibliography.htm#[Stroustrup]">[Stroustrup]</A></P>
<P><B>SOLUTION:</B>&nbsp;The C preprocessor&nbsp;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>&copy; 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>