120 lines
5.3 KiB
HTML
120 lines
5.3 KiB
HTML
|
<html>
|
|||
|
<head>
|
|||
|
<title>motivation.html</title>
|
|||
|
<link rel="stylesheet" type="text/css" href="../styles.css">
|
|||
|
</head>
|
|||
|
<body>
|
|||
|
<h4>Motivation</h4>
|
|||
|
<div>
|
|||
|
The C++ function and template parameter lists are special syntactic constructs, and it is impossible to directly
|
|||
|
manipulate or generate them using C++ constructs.
|
|||
|
This leads to unnecessary code repetition.
|
|||
|
</div>
|
|||
|
<div>
|
|||
|
Consider the implementation of the <code>is_function<></code> metafunction is Boost.
|
|||
|
The implementation uses an overloaded <code>is_function_tester()</code> function that is used for testing if a type is convertible
|
|||
|
to a pointer to a function.
|
|||
|
Because of the special treatment of parameter lists, it is not possible to directly match a function with an arbitrary parameter list.
|
|||
|
Instead, the <code>is_function_tester()</code> must be overloaded for every distinct number of parameters that is to be supported.
|
|||
|
For example:
|
|||
|
</div>
|
|||
|
<div class="code"><pre>
|
|||
|
template<class R>
|
|||
|
yes_type is_function_tester(R (*)());
|
|||
|
|
|||
|
template<class R, class A0>
|
|||
|
yes_type is_function_tester(R (*)(A0));
|
|||
|
|
|||
|
template<class R, class A0, class A1>
|
|||
|
yes_type is_function_tester(R (*)(A0, A1));
|
|||
|
|
|||
|
template<class R, class A0, class A1, class A2>
|
|||
|
yes_type is_function_tester(R (*)(A0, A1, A2));
|
|||
|
|
|||
|
// ...
|
|||
|
</pre></div>
|
|||
|
<div>
|
|||
|
The need for this kind of repetition occurs particularly frequently while implementing generic components or metaprogramming facilities,
|
|||
|
but the need also manifests itself in many far simpler situations.
|
|||
|
</div>
|
|||
|
<h4>Typical Solutions</h4>
|
|||
|
<div>
|
|||
|
Typically the repetition is done manually.
|
|||
|
Manual code repetition is highly unproductive, but sometimes more readable to the untrained eye.
|
|||
|
</div>
|
|||
|
<div>
|
|||
|
Another solution is to write an external program for generating the repeated code or use some other extra linguistic means such as a smart editor.
|
|||
|
Unfortunately, using external code generators has many disadvantages:
|
|||
|
<ul>
|
|||
|
<li>Writing the generator takes time. (This could be helped by using a standard generator.)</li>
|
|||
|
<li>It is no longer productive to manipulate C++ code directly.</li>
|
|||
|
<li>Invoking the generator may be difficult.</li>
|
|||
|
<li>Automating the invocation of the generator can be difficult in certain environments. (Automatic invocation is desirable for active libraries.)</li>
|
|||
|
<li>Porting and distributing the generator may be difficult or simply takes precious time.</li>
|
|||
|
</ul>
|
|||
|
</div>
|
|||
|
<h4>What about the preprocessor?</h4>
|
|||
|
<div>
|
|||
|
Because C++ comes with a preprocessor, one would assume that it would support these kinds of needs directly.
|
|||
|
Using the preprocessor in this case is highly desirable because:
|
|||
|
<ul>
|
|||
|
<li>The preprocessor is highly portable.</li>
|
|||
|
<li>The preprocessor is automatically invoked as part of the compilation process.</li>
|
|||
|
<li>Preprocessor metacode can be directly embedded into the C++ source code.</li>
|
|||
|
<li>Compilers generally allow viewing or outputting the preprocessed code, which can be used for debugging or to copy and paste the generated code.</li>
|
|||
|
</ul>
|
|||
|
</div>
|
|||
|
<div>
|
|||
|
Most unfortunately, the preprocessor is a very low level preprocessor that specifically does not support repetition or recursive macros.
|
|||
|
Library support is needed!
|
|||
|
</div>
|
|||
|
<div>
|
|||
|
<i>For detailed information on the capabilities and limitations of the preprocessor, please refer to the C++ standard <a href="../bibliography.html#std">[Std]</a>.</i>
|
|||
|
</div>
|
|||
|
<h4>The Motivation Example Revisited</h4>
|
|||
|
<div>
|
|||
|
Using the primitives of the preprocessor library, the <code>is_function_tester()</code>'s could be implemented like this:
|
|||
|
</div>
|
|||
|
<div class="code"><pre>
|
|||
|
#include <boost/preprocessor/arithmetic/inc.hpp>
|
|||
|
#include <boost/preprocessor/punctuation/comma_if.hpp>
|
|||
|
#include <boost/preprocessor/repetition.hpp>
|
|||
|
|
|||
|
#ifndef MAX_IS_FUNCTION_TESTER_PARAMS
|
|||
|
#define MAX_IS_FUNCTION_TESTER_PARAMS 15
|
|||
|
#endif
|
|||
|
|
|||
|
#define IS_FUNCTION_TESTER(Z, N, _) \
|
|||
|
template<class R BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_PARAMS(N, class A)> \
|
|||
|
yes_type is_function_tester(R (*)(BOOST_PP_ENUM_PARAMS(N, A))); \
|
|||
|
/**/
|
|||
|
|
|||
|
BOOST_PP_REPEAT(BOOST_PP_INC(MAX_IS_FUNCTION_TESTER_PARAMS), IS_FUNCTION_TESTER, _)
|
|||
|
|
|||
|
#undef IS_FUNCTION_TESTER
|
|||
|
</pre></div>
|
|||
|
<div>
|
|||
|
In order to change the maximum number of function parameters supported, you now simply change the <code>MAX_IS_FUNCTION_TESTER_PARAMS</code> definition and recompile.
|
|||
|
</div>
|
|||
|
<hr size="1">
|
|||
|
<div style="margin-left: 0px;">
|
|||
|
<i><EFBFBD> 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><EFBFBD> Copyright <a href="http://www.housemarque.com" target="_top">Housemarque Oy</a> 2002</i>
|
|||
|
</br><i><EFBFBD> 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>
|