123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- <html>
- <head>
- <title>problems.html</title>
- <link rel="stylesheet" type="text/css" href="../styles.css">
- </head>
- <body>
- <h4>Known Problems of the C/C++ Preprocessor</h4>
- <div>
- 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 the preprocessor, then you should do it that way.
- </div>
- <div>
- Let's survey some of the widely known problems of the preprocessor in a problem/solution format.
- </div>
- <h4>Problem #1</h4>
- <div>
- The preprocessor does not respect scope, therefore macros can accidentally and sometimes silently replace code.
- </div>
- <div>
- <b>Solution A</b>
- <div>
- Use all caps identifiers for macros and only macros.
- This practically eliminates the possibility that a macro might replace other kinds of code accidentally.
- </div>
- </div>
- <div>
- <b>Solution B</b>
- <div>
- Use the local macro idiom:
- </div>
- <div class="code"><pre>
- #define MACRO ...
- // use MACRO
- #undef MACRO
- </pre></div>
- <div>
- This makes sure that a macro cannot accidentally replace code outside of the scope of the local macro.
- </div>
- <div>
- A problem with this solution is that the #undef cannot be automated and may be forgotten.
- Experienced programmers generally write the #undef either immediately before (in time)
- or immediately after writing the macro definition.
- </div>
- </div>
- <div>
- <b>Solution C</b>
- <div>
- Use the unique macro prefix idiom.
- </div>
- <div class="code"><pre>
- #define UMP_MACRO
- // use UMP_MACRO
- </pre></div>
- <div>
- This makes accidental substitution and collisions highly unlikely.
- Problems with this solution include:
- </div>
- <ul>
- <li>There can still be naming collisions inside a large project.</li>
- <li>Macros still pollute the global namespace.</li>
- </ul>
- <i>By combining all solutions, whenever possible, the scope problem can be largely avoided.</i>
- </div>
- <h4>Problem #2</h4>
- <div>
- Preprocessor code is difficult to read.
- It requires an understanding of the basic process of how the preprocessor recursively expands macros,
- finding macro definitions, and mentally substituting the parameters of the macro.
- </div>
- <div>
- <b>Solution</b>
- <div>
- Any kind of programming requires a basic understanding of how the code is executed.
- Any parameterization technique, including simple functions and templates requires finding
- the definition and mentally substituting parameters.
- </div>
- <div>
- However, it is good to know a few techniques:
- </div>
- <ul>
- <li>By using as many local macros as reasonable, the bulk of the searching process can be eliminated.</li>
- <li>Code browsers and text search tools make it easier to find the definitions.</li>
- <li>The compiler can be used for generating the preprocessed source code in order to look for bugs.</li>
- <li>
- Before turning something into a preprocessor metaprogram, first implement a small scale version
- of it without the preprocessor.
- The work bottom-up, replacing hand-written constructs by using the 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>
- <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>
- <i>An especially important thing to remember is to limit the use of the preprocessor to
- structured, well-understood, and safe methods.
- Structure helps to understand complex systems <a href="../bibliography.html#mcconnell">[McConnell]</a>.</i>
- </div>
- <h4>Problem #3</h4>
- <div>
- "I'd like to see Cpp abolished." - <i>Bjarne Stroustrup</i> in <a href="../bibliography.html#stroustrup">[Stroustrup]</a>.
- </div>
- <div>
- <b>Solution</b>
- <div>
- The C/C++ preprocessor will be here for a long time.
- </div>
- <i>In practice, preprocessor metaprogramming is far simpler and more portable than template metaprogramming <a href="../bibliography.html#czarnecki">[Czarnecki]</a>.</i>
- </div>
- <hr size="1">
- <div style="margin-left: 0px;">
- <i>© Copyright <a href="http://www.housemarque.com" target="_top">Housemarque Oy</a> 2002</i>
- </div>
- <div style="margin-left: 0px;">
- 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.
- </div>
- <hr size="1">
- <div style="margin-left: 0px;">
- <i>© Copyright <a href="http://www.housemarque.com" target="_top">Housemarque Oy</a> 2002</i>
- </br><i>© Copyright Paul Mensonides 2002</i>
- </div>
- <div style="margin-left: 0px;">
- <p><small>Distributed under the Boost Software License, Version 1.0. (See
- accompanying file <a href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
- copy at <a href=
- "http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</small></p>
- </div>
- </body>
- </html>
|