File: known_problems_with_cpp.htm

package info (click to toggle)
boost 1.27.0-3
  • links: PTS
  • area: main
  • in suites: woody
  • size: 19,908 kB
  • ctags: 26,546
  • sloc: cpp: 122,225; ansic: 10,956; python: 4,412; sh: 855; yacc: 803; makefile: 257; perl: 165; lex: 90; csh: 6
file content (124 lines) | stat: -rw-r--r-- 5,227 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Boost.Preprocessor - Widely known problems with the C preprocessor</title>
</head>
<body bgcolor="#FFFFFF" 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>

<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&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>

<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> &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><i>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.</i></p>
</body>
</html>