lib cleanup

[SVN r15693]
This commit is contained in:
Paul Mensonides
2002-10-03 22:13:37 +00:00
parent ae584c68b2
commit 4bb690a819
263 changed files with 14965 additions and 16 deletions

View File

@ -0,0 +1,146 @@
<html>
<head>
<title>evaluated_slots.html</title>
<link rel="stylesheet" type="text/css" href="../styles.css">
</head>
<body>
<h4>Evaluated Slots</h4>
<div>
The evaluated slot mechanism is a tool to fully evaluate a constant integral expression and avoid the lazy evaluation normally performed by the preprocessor.
</div>
<h4>Tutorial</h4>
<div>
In order to understand the use of such a mechanism, I will start with a simple file-iteration example.&nbsp;
Consider the following scenario....
</div>
<div class ="code"><pre>
for (int i = 0; i < 10; ++i) {
for (int j = 0; j < i; ++j) {
// ... use i and j
}
}
</pre></div>
<div>
The above is a simple runtime model of the following multidimensional file-iteration....
</div>
<div class="code"><pre>
// file.hpp
#if !BOOST_PP_IS_ITERATING
#ifndef FILE_HPP_
#define FILE_HPP_
#include &lt;boost/preprocessor/iteration/iterate.hpp&gt;
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 9, "file.hpp"))
#include BOOST_PP_ITERATE()
#endif // FILE_HPP_
#elif BOOST_PP_ITERATION_DEPTH() == 1
#define I BOOST_PP_ITERATION()
#define BOOST_PP_ITERATION_PARAMS_2 (3, (0, I, "file.hpp"))
#include BOOST_PP_ITERATE()
#undef I
#elif BOOST_PP_ITERATION_DEPTH() == 2
#define J BOOST_PP_ITERATION()
// use I and J
#undef J
#endif
</pre></div>
<div>
There is a problem with the code above.&nbsp;
The writer expected <i>I</i> to refer the previous iteration frame.&nbsp;
However, that is not the case.&nbsp;
When the user refers to <i>I</i>, he is actually referring to <b>BOOST_PP_ITERATION</b>(),
not the value of <b>BOOST_PP_ITERATION</b>() at the point of definition.&nbsp;
Instead, it refers to exactly the same value to which <i>J</i> refers.
</div>
<div>
The problem is that the preprocessor always evaluates everything with lazy evaluation.&nbsp;
To solve the problem, we need <i>I</i> to be <i>evaluated</i> here:
</div>
<div class="code"><pre>
// ...
#elif BOOST_PP_ITERATION_DEPTH() == 1
#define I BOOST_PP_ITERATION()
// ...
</pre></div>
<div>
Fortunately, the library offers a mechanism to do just that:&nbsp; evaluated slots.&nbsp;
The following code uses this mechanism to "fix" the example above...
</div>
<div class="code"><pre>
// ...
#elif BOOST_PP_ITERATION_DEPTH() == 1
#define BOOST_PP_VALUE BOOST_PP_ITERATION()
#include BOOST_PP_ASSIGN_SLOT(1)
#define I BOOST_PP_SLOT(1)
// ...
</pre></div>
<div>
There are two steps to the assignment of an evaluated slot.&nbsp;
First, the user must define the <i>named external argument</i> <b>BOOST_PP_VALUE</b>.&nbsp;
This value must be an integral constant expression.&nbsp;
Second, the user must <i>include</i> <b>BOOST_PP_ASSIGN_SLOT</b>(<i>x</i>), where <i>x</i> is the particular slot to be assigned to (<i>1</i> to <b>BOOST_PP_LIMIT_SLOT_COUNT</b>).&nbsp;
This will evaluate <b>BOOST_PP_VALUE</b> and assign the result to the slot at index <i>x</i>.
</div>
<div>
To retrieve a slot's value, the user must use <b>BOOST_PP_SLOT</b>(<i>x</i>).
</div>
<div>
In the case above, <i>I</i> is <i>still</i> lazily evaluated.&nbsp;
However, it now evaluates to <b>BOOST_PP_SLOT</b>(<i>1</i>).&nbsp;
This value <i>will not change</i> unless there is a subsequent call to <b>BOOST_PP_ASSIGN_SLOT</b>(<i>1</i>).
</div>
<h4>Advanced Techniques</h4>
<div>
The slot mechanism can also be used to perform calculations:
</div>
<div class="code"><pre>
#include &lt;iostream&gt;
#include &lt;boost/preprocessor/slot/slot.hpp&gt;
#include &lt;boost/preprocessor/stringize.hpp&gt;
#define X() 4
#define BOOST_PP_VALUE 1 + 2 + 3 + X()
#include BOOST_PP_ASSIGN_SLOT(1)
#undef X
int main(void) {
std::cout
&lt;&lt; BOOST_PP_STRINGIZE(BOOST_PP_SLOT(1))
&lt;&lt; &amp;std::endl;
return 0;
}
</pre></div>
<div>
In essence, anything that can be evaluated in an #if (or #elif) preprocessor directive is available <i>except</i> the <i>defined</i> operator.
</div>
<div>
It is even possible to use a particular slot itself while reassigning it:
</div>
<div class="code"><pre>
#define BOOST_PP_VALUE 20
#include BOOST_PP_ASSIGN_SLOT(1)
#define BOOST_PP_VALUE 2 * BOOST_PP_SLOT(1)
#include BOOST_PP_ASSIGN_SLOT(1)
BOOST_PP_SLOT(1) // 40
</pre></div>
<h4>See Also</h4>
<ul>
<li><a href="../ref/assign_slot.html">BOOST_PP_ASSIGN_SLOT</a></li>
<li><a href="../ref/limit_slot_count.html">BOOST_PP_LIMIT_SLOT_COUNT</a></li>
<li><a href="../ref/slot.html">BOOST_PP_SLOT</a></li>
<li><a href="../ref/value.html">BOOST_PP_VALUE</a></li>
</ul>
<div class="sig">- Paul Mensonides</div>
</body>
</html>

View File

@ -0,0 +1,921 @@
<html>
<head>
<title>file_iteration.html</title>
<link rel="stylesheet" type="text/css" href="../styles.css">
</head>
<body>
<h4>File Iteration</h4>
<div>
File iteration is a complex, but powerful, vertical repetition construct.&nbsp;
It repeatedly includes a <i>file</i> for each number in a user-specified range.
</div>
<h4>Tutorial</h4>
<div>
This mechanism requires two pieces of information to operate:&nbsp;
a range to iterate over and a file to include on each iteration.&nbsp;
It can optionally take a third piece of information that represents flags used to discriminate between
different iterations of the same file.&nbsp;
This information is obtained by the mechanism through one or two <i>named external arguments</i>.&nbsp;
These arguments are specified as user-defined macros named <b>BOOST_PP_ITERATION_PARAMS_<i>x</i></b>
or the combination of <b>BOOST_PP_FILENAME_<i>x</i></b> and <b>BOOST_PP_ITERATION_LIMITS</b>.
</div>
<div>
<b>BOOST_PP_ITERATION_LIMITS</b> specifies the range of values to iterate over.&nbsp;
It <i>must</i> expand to a <i>tuple</i> containing two elements--a lower and upper bound.&nbsp;
Both the upper and lower bounds must be numeric values in the range of <i>0</i> to <b>BOOST_PP_LIMIT_ITERATION</b>.&nbsp;
For example, if the user wishes a file to be included for numbers ranging from <i>0</i> to <i>10</i>,
<b>BOOST_PP_ITERATION_LIMITS</b> would be defined like this:
</div>
<div class="code"><pre>
#define BOOST_PP_ITERATION_LIMITS (0, 10)
</pre></div>
<div>
Note that there is whitespace after the name of the macro.&nbsp;
The macro <i>does not</i> take <i>two</i> arguments.&nbsp;
In the case above, if there was no whitespace, a preprocessing error would occur because <i>0</i> and <i>10</i>
are invalid identifiers.
</div>
<div>
Both the upper and lower bounds specified in the <b>BOOST_PP_ITERATION_LIMITS</b> macro are <i>evaluated parameters</i>.&nbsp;
This implies that they can include simple arithmetic or logical expressions.&nbsp;
For instance, the above definition could easily have been written like this:
</div>
<div class="code"><pre>
#define N() 5
#define BOOST_PP_ITERATION_LIMITS (0, N() + 5)
</pre></div>
<div>
Because of this, if the whitespace after the macro name is elided, it is possible for the
definition to be syntactically valid:
</div>
<div class="code"><pre>
#define A 0
#define B 10
#define BOOST_PP_ITERATION_LIMITS(A, B)
// note: no whitespace ^
</pre></div>
<div>
If this happens, an error will occur inside the mechanism when it attempts to use this macro.&nbsp;
The error messages that result may be obscure, so always remember to include the whitespace.&nbsp;
A <i>correct</i> version of the above looks like this:
</div>
<div class="code"><pre>
#define A 0
#define B 10
#define BOOST_PP_ITERATION_LIMITS (A, B)
// note: has whitespace ^
</pre></div>
<div>
<b>BOOST_PP_FILENAME_<i>x</i></b> specifies the file to iterate over.&nbsp;
The <i>x</i> is a placeholder for the dimension of iteration.&nbsp;
(For now, we'll assume this is <i>1</i>--i.e. the first dimension,
so we are actually dealing with <b>BOOST_PP_FILENAME_1</b>.)&nbsp;
This macro must expand to a valid filename--in quotes or in angle brackets depending on how the file is accessed:
</div>
<div class="code"><pre>
#define BOOST_PP_FILENAME_1 "file.h"
// -or-
#define BOOST_PP_FILENAME_1 &lt;file.h&gt;
</pre></div>
<div>
All that we need now to perform a simple file iteration is to invoke the mechanism:
</div>
<div class="code"><pre>
??=include BOOST_PP_ITERATE()
</pre></div>
<div>
(The <code>??=</code> token is a trigraph for <code>#</code>.&nbsp;
I use the trigraph to make it clear that I am <i>including</i> a file rather than defining or expanding a macro, but it is not necessary.&nbsp;
Even the digraph version, <code>%:</code>, could be used.&nbsp;
Some compilers do not readily accept trigraphs and digraphs, so keep that in mind.&nbsp;
Other than that, use whichever one you prefer.)
</div>
<div>
So, if we wish to iterate "file.h" from <i>1</i> to <i>10</i>, we just need to put the pieces together:
</div>
<div class="code"><pre>
#define BOOST_PP_ITERATION_LIMITS (1, 10)
#define BOOST_PP_FILENAME_1 "file.h"
??=include BOOST_PP_ITERATE()
</pre></div>
<div>
The above code has the effect of including "file.h" ten times in succession.&nbsp;
</div>
<div>
Alternately, both the range and the file to iterate over can be expressed in one macro, <b>BOOST_PP_ITERATION_PARAMS_<i>x</i></b>.&nbsp;
Once again, the <i>x</i> is a placeholder for the dimension of iteration--which we'll assume is <i>1</i>.&nbsp;
This macro must expand to an <i>array</i> that includes the lower bound, upper bound, filename, and optional flags (in that order).
</div>
<div class="code"><pre>
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 10, "file.h"))
??=include BOOST_PP_ITERATE()
</pre></div>
<div>
This has the same effect as the previous version.&nbsp;
Only one of these two ways to specify the parameters can be used at a time.&nbsp;
(The reason that there are two different methods has to do with dimensional abstraction which I'll get to later.)
</div>
<div>
There is nothing particularly useful about including a file ten times.&nbsp;
The difference is that the current macro state changes each time.&nbsp;
For example, the current "iteration value" is available with <b>BOOST_PP_ITERATION</b>().&nbsp;
If "file.h" is defined like this...
</div>
<div class="code"><pre>
// file.h
template&lt;&gt; struct sample&lt;BOOST_PP_ITERATION()&gt; { };
</pre></div>
<div>
...and it is iterated as follows...
</div>
<div class="code"><pre>
template&lt;int&gt; struct sample;
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 5, "file.h"))
??=include BOOST_PP_ITERATE()
</pre></div>
<div>
...the result is different each time:
</div>
<div><pre>
template&lt;&gt; struct sample&lt;1&gt; { };
template&lt;&gt; struct sample&lt;2&gt; { };
template&lt;&gt; struct sample&lt;3&gt; { };
template&lt;&gt; struct sample&lt;4&gt; { };
template&lt;&gt; struct sample&lt;5&gt; { };
</pre></div>
<div>
There is no reason that a file can't iterate over itself.&nbsp;
This has the advantage of keeping the code together.&nbsp;
The problem is that you have to discriminate the "regular" section of the file from the iterated section of the file.&nbsp;
The library provides the <b>BOOST_PP_IS_ITERATING</b> macro to help in this regard.&nbsp;
This macro is defined as <i>1</i> if an iteration is in progress.&nbsp;
For example, to merge the contents of "file.h" into the file that iterates it:
</div>
<div class="code"><pre>
// sample.h
#if !BOOST_PP_IS_ITERATING
#ifndef SAMPLE_H
#define SAMPLE_H
#include &lt;boost/preprocessor/iteration/iterate.hpp&gt;
template&lt;int&gt; struct sample;
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 5, "sample.h"))
??=include BOOST_PP_ITERATE()
#endif // SAMPLE_H
#else
template&lt;&gt; struct sample&lt;BOOST_PP_ITERATION()&gt; { };
#endif
</pre></div>
<div>
Using the same file like this raises another issue.&nbsp;
What happens when a file performs two separate file iterations over itself?&nbsp;
This is the purpose of the optional flags parameter.&nbsp;
It is used to discriminate between separate iterations.
</div>
<div class="code"><pre>
// sample.h
#if !BOOST_PP_IS_ITERATING
#ifndef SAMPLE_H
#define SAMPLE_H
#include &lt;boost/preprocessor/iteration/iterate.hpp&gt;
#include &lt;boost/preprocessor/repetition/enum_params.hpp&gt;
#include &lt;boost/preprocessor/repetition/enum_shifted_params.hpp&gt;
template&lt;int&gt; struct sample;
#define BOOST_PP_ITERATION_PARAMS_1 (4, (1, 5, "sample.h", 1))
??=include BOOST_PP_ITERATE()
template&lt;class T, class U&gt; struct typelist_t {
typedef T head;
typedef U tail;
};
template&lt;int&gt; struct typelist;
struct null_t;
template&lt;&gt; struct typelist&lt;1&gt; {
template&lt;class T0&gt; struct args {
typedef typelist_t&lt;T0, null_t&gt; type;
};
};
#ifndef TYPELIST_MAX
#define TYPELIST_MAX 50
#endif
#define BOOST_PP_ITERATION_PARAMS_1 (4, (2, TYPELIST_MAX, "sample.h", 2))
??=include BOOST_PP_ITERATE()
#endif // SAMPLE_H
#elif BOOST_PP_ITERATION_FLAGS() == 1
template&lt;&gt; struct sample&lt;BOOST_PP_ITERATION()&gt; { };
#elif BOOST_PP_ITERATION_FLAGS() == 2
#define N BOOST_PP_ITERATION()
template&lt;&gt; struct typelist&lt;N&gt; {
template&lt;BOOST_PP_ENUM_PARAMS(N, class T)&gt; struct args {
typedef typelist_t&lt;
T0,
typename typelist&lt;N - 1&gt;::args&lt;BOOST_PP_ENUM_SHIFTED_PARAMS(N, T)&gt;::type
&gt; type;
};
};
#undef N
#endif
</pre></div>
<div>
Notice the use of the "flags" parameter (which is accessed through <b>BOOST_PP_ITERATION_FLAGS</b>()).&nbsp;
It discriminates between our recurring <code>sample</code> iteration and a typelist linearization iteration.&nbsp;
</div>
<div>
The second iteration illustrates the power of the file iteration mechanism.&nbsp;
It generates typelist linearizations of the form <code>typelist&lt;3&gt;::args&lt;int, double, char&gt;::type</code>.
</div>
<div>
Actually, to continue the typelist example, with the help of another iteration we can <i>fully</i> linearize typelist creation....
</div>
<div class="code"><pre>
// extract.h
#if !BOOST_PP_IS_ITERATING
#ifndef EXTRACT_H
#define EXTRACT_H
#include &lt;boost/preprocessor/iteration/iterate.hpp&gt;
#include &lt;boost/preprocessor/repetition/enum.hpp&gt;
#include &lt;boost/preprocessor/repetition/enum_params.hpp&gt;
#include &lt;boost/preprocessor/repetition/enum_trailing_params.hpp&gt;
// certain types such as "void" can't be function argument types
template&lt;class T&gt; struct incomplete {
typedef T type;
};
template&lt;class T&gt; struct strip_incomplete {
typedef T type;
};
template&lt;class T&gt; struct strip_incomplete&lt;incomplete&lt;T&gt; &gt; {
typedef T type;
};
template&lt;template&lt;int&gt; class output, class func_t&gt; struct extract;
#ifndef EXTRACT_MAX
#define EXTRACT_MAX 50
#endif
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, EXTRACT_MAX, "extract.h"))
??=include BOOST_PP_ITERATE()
#endif // EXTRACT_H
#else
#define N BOOST_PP_ITERATION()
#define STRIP(z, n, _) \
typename strip_incomplete&lt;T ## n&gt;::type \
/**/
template&lt;template&lt;int&gt; class output, class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)&gt;
struct extract&lt;R (BOOST_PP_ENUM_PARAMS(N, T))&gt; {
typedef typename output&lt;N&gt;::template args&lt;BOOST_PP_ENUM(N, STRIP, nil)&gt;::type type;
};
#undef STRIP
#undef N
#endif
</pre></div>
<div>
Now we can define a helper macro to finish the job:
</div>
<div class="code"><pre>
#define TYPELIST(args) extract&lt;typelist, void args&gt;::type
typedef TYPELIST((int, double, incomplete&lt;void&gt;)) xyz;
</pre></div>
<div>
There are two minor caveats with this result.&nbsp;
First, certain types like <code>void</code> can't be the type of an argument, so they have to be
wrapped with <code>incomplete&lt;T&gt;</code>.&nbsp;
Second, the necessary double parenthesis is annoying.&nbsp;
If and when C++ gets C99's variadic macros, <code>TYPELIST</code> can be redefined:
</div>
<div class="code"><pre>
#define TYPELIST(...) extract&lt;typelist, void (__VA_ARGS__)&gt;::type
typedef TYPELIST(int, double, short) xyz;
</pre></div>
<div>
Note also that both the lower and upper bounds of an iteration are also accessible inside an iteration with
<b>BOOST_PP_ITERATION_START</b>() and <b>BOOST_PP_ITERATION_FINISH</b>().
</div>
<div>
It is my hope that the explanation and examples presented here demonstrate the power of file iteration.&nbsp;
Even so, this is just the beginning.&nbsp;
The file iteration mechanism also defines a full suite of facilities to support multidimensional iteration.
</div>
<h4>Multiple Dimensions</h4>
<div>
The file iteration mechanism supports up to <b>BOOST_PP_LIMIT_ITERATION_DIM</b> dimensions.&nbsp;
The first dimension (i.e. the outermost) we have already used above.&nbsp;
In order to use the second dimension (inside the first), we simply have to replace the placeholder <i>x</i>
with <i>2</i> instead of <i>1</i>.
</div>
<div class="code"><pre>
#define BOOST_PP_ITERATION_PARAMS_2 /* ... */
^
</pre></div>
<div>
...or...
</div>
<div class="code"><pre>
#define BOOST_PP_FILENAME_2 /* ... */
^
</pre></div>
<div>
Each dimension must be used <i>in order</i> starting with <i>1</i>.&nbsp;
Therefore, the above can <i>only</i> be valid immediately inside the first dimension.&nbsp;
</div>
<div>
At this point, further explanation is necessary regarding <b>BOOST_PP_ITERATION</b>,
<b>BOOST_PP_ITERATION_START</b>, and <b>BOOST_PP_ITERATION_FINISH</b>.&nbsp;
<b>BOOST_PP_ITERATION</b>() expands to the iteration value of the <i>current</i> dimension--regardless
of what dimension that is.&nbsp;
Likewise, <b>BOOST_PP_ITERATION_START</b>() and <b>BOOST_PP_ITERATION_FINISH</b>() expand to the lower
and upper bounds of the <i>current</i> dimension.&nbsp;
Using the following pseudo-code as reference:
</div>
<div class="code"><pre>
for (int i = start(1); i <= finish(1); ++i) {
// A
for (int j = start(2); j <= finish(2); ++j) {
// B
}
// C
}
</pre></div>
<div>
At point <i>A</i>, <b>BOOST_PP_ITERATION</b>() refers to <code>i</code>.&nbsp;
<b>BOOST_PP_ITERATION_START</b>() and <b>BOOST_PP_ITERATION_FINISH</b>()
refer to <code>start(1)</code> and <code>finish(1)</code> respectively.&nbsp;
At point <i>B</i>, however, <b>BOOST_PP_ITERATION</b>() refers to <code>j</code>--the <i>current</i>
iteration value at point <i>B</i>.&nbsp;
The same is true for <b>BOOST_PP_ITERATION_START</b>() which refers to <code>start(2)</code>, etc..
</div>
<div>
If separate files are used for each dimension, then there are no major problems, and using multiple dimensions is straightforward.&nbsp;
However, if more than one dimension is located in the same file, they need to be distinguished from one another.&nbsp;
The file iteration mechanism provides the macro <b>BOOST_PP_ITERATION_DEPTH</b> for this purpose:
</div>
<div class="code"><pre>
// file.h
#if !BOOST_PP_IS_ITERATING
#ifndef FILE_H
#define FILE_H
#include &lt;boost/preprocessor/iteration/iterate.hpp&gt;
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 2, "file.h"))
??=include BOOST_PP_ITERATE()
#endif // FILE_H
#elif BOOST_PP_ITERATION_DEPTH() == 1
// A
+ BOOST_PP_ITERATION()
#define BOOST_PP_ITERATION_PARAMS_2 (3, (1, 2, "file.h"))
??=include BOOST_PP_ITERATE()
// C
#elif BOOST_PP_ITERATION_DEPTH() == 2
// B
- BOOST_PP_ITERATION()
#endif
</pre></div>
<div>
This will result to the following:
</div>
<div><pre>
+ 1
- 1
- 2
+ 2
- 1
- 2
</pre></div>
<div>
Multiple dimensions raise another question.&nbsp;
How does one access the state of dimensions <i>other</i> than the current dimension?&nbsp;
In other words, how does one access <code>i</code> at point <i>A</i>?&nbsp;
Because of the preprocessor's lazy evaluation, this <i>doesn't</i> work....
</div>
<div class="code"><pre>
// ...
#elif BOOST_PP_ITERATION_DEPTH() == 1
#define I BOOST_PP_ITERATION()
#define BOOST_PP_ITERATION_PARAMS_2 (3, (1, 2, "file.h"))
??=include BOOST_PP_ITERATE()
#undef I
#elif BOOST_PP_ITERATION_DEPTH() == 2
#define J BOOST_PP_ITERATION()
// use I and J
#undef I
#endif
</pre></div>
<div>
The problem here is that <code>I</code> refers to <b>BOOST_PP_ITERATION</b>(),
not to the <i>value</i> of <b>BOOST_PP_ITERATION</b>() at the point of <code>I</code>'s definition.
</div>
<div>
The library provides macros to access these values in two ways--absolutely or relatively.&nbsp;
The first variety accesses a value of a specific iteration frame (i.e. dimension).&nbsp;
To access the iteration value of the first dimension--from <i>any</i> dimension--<b>BOOST_PP_FRAME_ITERATION</b>(<i>1</i>) is used.&nbsp;
To access the iteration value of the second dimension, <b>BOOST_PP_FRAME_ITERATION</b>(<i>2</i>) is used, and so on.&nbsp;
</div>
<div>
There are also frame versions to access the lower bound, the upper bound, and the flags of a dimension:&nbsp;
<b>BOOST_PP_FRAME_START</b>, <b>BOOST_PP_FRAME_FINISH</b>, and <b>BOOST_PP_FRAME_FLAGS</b>.
</div>
<div>
So, to fix the last example, we modify the definition of <code>I</code>....
</div>
<div class="code"><pre>
// ...
#elif BOOST_PP_ITERATION_DEPTH() == 1
#define I BOOST_PP_FRAME_ITERATION(1)
// ...
</pre></div>
<div>
The library also provides macros to access values in dimensions <i>relative</i> to the current dimension (e.g. the <i>previous</i> dimension).&nbsp;
These macros take an argument that is interpreted as an offset from the current frame.&nbsp;
For example, <b>BOOST_PP_RELATIVE_ITERATION</b>(<i>1</i>) always refers to the outer dimension immediately previous to the current dimension.&nbsp;
An argument of <i>0</i> is interpreted as an offset of <i>0</i> which causes
<b>BOOST_PP_RELATIVE_ITERATION</b>(<i>0</i>) to be equivalent to <b>BOOST_PP_ITERATION</b>().&nbsp;
<b>BOOST_PP_RELATIVE_ITERATION</b>(<i>2</i>) refers to the iteration value of the dimension immediately preceding
the dimension that precedes the current dimension.&nbsp;
</div>
<div>
The lower and upper bounds of a dimension can be accessed in this fashion as well
with <b>BOOST_PP_RELATIVE_START</b> and <b>BOOST_PP_RELATIVE_FINISH</b>.&nbsp;
The flags of a relative dimension can be accessed with <b>BOOST_PP_RELATIVE_FLAGS</b>.
</div>
<h4>Relativity</h4>
<div>
I mentioned earlier that there is a reason that there are two ways to parametize the mechanism.&nbsp;
The reason is dimensional abstraction.&nbsp;
In certain situations the dimension is unknown by the code that is being iterated--possibly
because the code is reused at multiple, different dimensions.&nbsp;
If that code needs to iterate again, it has to define the right parameters (based on the dimension) for the mechanism to consume.&nbsp;
</div>
<div>
All of the macro state maintained by the mechanism can be referred to in an indirect way relative to a dimension.&nbsp;
This is the purpose of the <b>BOOST_PP_RELATIVE_</b> accessors.&nbsp;
</div>
<div>
Likewise, the user-defined <i>named external arguments</i> can be defined this way as well--<i>except</i> the name of the file to iterate.&nbsp;
Because the lower and upper boundaries are <i>evaluated</i> by the mechanism, the implementation no longer needs
the macro <b>BOOST_PP_ITERATION_LIMITS</b>, and the identifier can be reused for each dimension of iteration.&nbsp;
</div>
<div>
Unfortunately, the filename is a different story.&nbsp;
The library has no way to evaluate the quoted (or angle-bracketed) text.&nbsp;
Therefore, it has to use a different macro for each dimension.&nbsp;
That is the purpose of the <b>BOOST_PP_FILENAME_<i>x</i></b> macros.&nbsp;
They exist to isolate the only non-abstractable piece of data required by the mechanism.&nbsp;
</div>
<div>
In order to define the filename in an abstract fashion, you need to do something like this:
</div>
<div class="code"><pre>
#define UNIQUE_TO_FILE "some_file.h"
#if BOOST_PP_ITERATION_DEPTH() == 0
#define BOOST_PP_FILENAME_1 UNIQUE_TO_FILE
#elif BOOST_PP_ITERATION_DEPTH() == 1
#define BOOST_PP_FILENAME_2 UNIQUE_TO_FILE
#elif BOOST_PP_ITERATION_DEPTH() == 2
#define BOOST_PP_FILENAME_3 UNIQUE_TO_FILE
// ... up to BOOST_PP_LIMIT_ITERATION_DIM
#endif
</pre></div>
<div>
The intent is to avoid having to do this for anything but the filename.&nbsp;
If this needs to be done more than once in a file
(<b>BOOST_PP_FILENAME_<i>x</i></b> is undefined by the mechanism after it is used.),
consider using a separate file to make the proper definition:
</div>
<div class="code"><pre>
# // detail/define_file_h.h
# ifndef FILE_H
# error FILE_H is not defined
# endif
#
# if BOOST_PP_ITERATION_DEPTH() == 0
# define BOOST_PP_FILENAME_1 FILE_H
# elif BOOST_PP_ITERATION_DEPTH() == 1
# define BOOST_PP_FILENAME_2 FILE_H
# elif BOOST_PP_ITERATION_DEPTH() == 2
# define BOOST_PP_FILENAME_3 FILE_H
# elif BOOST_PP_ITERATION_DEPTH() == 3
# define BOOST_PP_FILENAME_4 FILE_H
# elif BOOST_PP_ITERATION_DEPTH() == 4
# define BOOST_PP_FILENAME_5 FILE_H
# else
# error unsupported iteration dimension
# endif
</pre></div>
<div>
And then use it like this....
</div>
<div class="code"><pre>
// file.h
#if !BOOST_PP_IS_ITERATING
#ifndef FILE_H
#define FILE_H "file.h"
#define BOOST_PP_ITERATION_LIMITS (1, 10)
#include "detail/define_file_h.h"
??=include BOOST_PP_ITERATE()
#endif // FILE_H
#else
// iterated portion
#endif
</pre></div>
<div>
With a little effort like this, it is possible to maintain the abstraction without the code bloat that would
otherwise be required.&nbsp;
Unfortunately, this is not a completely general solution as it would need to be done for each unique filename,
but it is better than nothing.
</div>
<h4>Conclusion</h4>
<div>
That about covers the facilities that are available from the mechanism.&nbsp;
Using these facilities, let's implement a <code>function_traits</code> template to demonstrate a full-fledge
use of the mechanism.
</div>
<h4>Function Traits - An Involved Example</h4>
<div>
Implementing a comprehensive <code>function_traits</code> template metafunction requires the use
of every major part of the file iteration mechanism.&nbsp;
</div>
<div>
(This example makes no attempt of work around compiler deficiencies and exists only to illustrate the mechanism.)
</div>
<div>
The result should have the following features:
</div>
<ul>
<li>return type</li>
<li>number and types of parameters</li>
<li>whether or not the type is a pointer-to-function, reference-to-function, pointer-to-member-function, or a plain function type</li>
<li>whether the type has an ellipsis</li>
<li>if not a pointer-to-member-function, the equivalent pointer-to-function, reference-to-function, and function type</li>
<li>otherwise, the pointer-to-member type, the class type to which it refers, and whether it is const and/or volatile qualified</li>
</ul>
<div>
There are a myriad of ways that this can be implemented.&nbsp;
I'll give a brief summary here of what is happening in the implementation below.&nbsp;
</div>
<div>
The implementation inherently has to deal with function arity.&nbsp;
Therefore, at minimum, we need to iterate over function arities and define partial specializations of
the primary template <code>function_traits</code>.&nbsp;
The situation is further complicated by variadic functions (i.e. functions with an ellipsis).&nbsp;
Therefore, for every arity, we need a variadic version as well.
</div>
<div>
We also need to handle pointers-to-member-functions.&nbsp;
This implies that we have to handle not just arity and variadics, but also cv-qualifications.&nbsp;
</div>
<div>
For the sake of clarity, the implementation below handles function types and pointers-to-member-functions
separately.&nbsp;
They could be merged, but the result would be significantly messier.
</div>
<div>
To handle function types, the implementation below iterates over function arities.&nbsp;
For each arity, it iterates over each parameter to provide access to each individually.&nbsp;
It then re-includes itself to define a variadic specialization of the same arity.&nbsp;
It performs the rough equivalent of the following pseudo-code:
</div>
<div class="code"><pre>
void make_spec(int i, bool variadic) {
:open function_traits&lt;i, variadic&gt;
for (int j = 0; j < i; ++j) {
:parameter&lt;j&gt;
}
:close
if (!variadic) {
make_spec(i, true);
}
return;
}
void function_types(int max_arity) {
for (int i = 0; i <= max_arity; ++i) {
make_spec(i, false);
}
return;
}
</pre></div>
<div>
The implementation of pointers-to-member-functions is a bit different.&nbsp;
First, it iterates over cv-qualifiers.&nbsp;
For each cv-qualifier, it iterates over function arities.&nbsp;
For each function arity, it iterates again over each parameter.&nbsp;
It then re-includes itself to define a variadic specialization of the same arity....
</div>
<div class="code"><pre>
void make_spec(int j, const char* cv, bool variadic) {
:open function_traits&lt;j, cv, variadic&gt;
for (int k = 0; k < j; ++k) {
parameter&lt;k&gt;
}
:close
if (!variadic) {
make_spec(j, cv, true);
}
return;
}
void gen_arities(const char* cv, int max_arity) {
for (int j = 0; j <= max_arity; ++j) {
make_spec(j, cv, false);
}
return;
}
void pointers_to_members(int max_arity) {
static const char* cv_qualifiers[] = { "", "const", "volatile", "const volatile" };
for (int i = 0; i < 4; ++i) {
gen_arities(cv_qualifiers[i], max_arity);
}
return;
}
</pre></div>
<div>
Here is the complete implementation.&nbsp;
This example represents the power of the file iteration mechanism as well as the library in general,
so follow it carefully if you wish to fully understand what the mechanism does....
</div>
<div class="code"><pre>
// function_traits.hpp
#if !BOOST_PP_IS_ITERATING
#ifndef FUNCTION_TRAITS_HPP
#define FUNCTION_TRAITS_HPP
#include &lt;boost/preprocessor/cat.hpp&gt;
#include &lt;boost/preprocessor/facilities/apply.hpp&gt;
#include &lt;boost/preprocessor/iteration/iterate.hpp&gt;
#include &lt;boost/preprocessor/iteration/self.hpp&gt;
#include &lt;boost/preprocessor/repetition/enum_params.hpp&gt;
#include &lt;boost/preprocessor/repetition/enum_trailing_params.hpp&gt;
#include &lt;boost/preprocessor/tuple/elem.hpp&gt;
// enable user-expansion
#ifndef FUNCTION_TRAITS_MAX_ARITY
#define FUNCTION_TRAITS_MAX_ARITY 15
#endif
namespace detail {
// avoid replication of "default" values
struct function_traits_base {
static const bool is_plain = false;
static const bool is_pointer = false;
static const bool is_reference = false;
static const bool is_member = false;
};
} // detail
// no definition
template&lt;class&gt; struct function_traits;
// extract ellipsis state
#define ELLIPSIS(n) \
BOOST_PP_APPLY( \
BOOST_PP_TUPLE_ELEM(2, n, ELLIPSIS_I) \
) \
/**/
// iterate over function arities for function types
#define BOOST_PP_ITERATION_PARAMS_1 \
(4, (0, FUNCTION_TRAITS_MAX_ARITY, "function_traits.hpp", 0)) \
/**/
??=include BOOST_PP_ITERATE()
// obtain a cv-qualifier by index
#define QUALIFIER(n) \
BOOST_PP_APPLY( \
BOOST_PP_TUPLE_ELEM( \
4, n, \
(BOOST_PP_NIL, (const), (volatile), (const volatile)) \
) \
) \
/**/
// iterate over cv-qualifiers for pointers-to-members
#define BOOST_PP_ITERATION_PARAMS_1 \
(4, (0, 3, "function_traits.hpp", 1)) \
/**/
??=include BOOST_PP_ITERATE()
// remove temporary macros
#undef QUALIFIER
#undef ELLIPSIS
// overriding jumper for pointers-to-functions
template&lt;class T&gt; struct function_traits&lt;T*&gt; : function_traits&lt;T&gt; {
static const bool is_plain = false;
static const bool is_pointer = true;
};
// overriding jumper for references-to-functions
template&lt;class T&gt; struct function_traits&lt;T&amp;&gt; : function_traits&lt;T&gt; {
static const bool is_plain = false;
static const bool is_reference = true;
};
// eof
#endif // FUNCTION_TRAITS_HPP
// specializations for function types
#elif BOOST_PP_ITERATION_DEPTH() == 1 \
&amp;&amp; BOOST_PP_ITERATION_FLAGS() == 0 \
/**/
// define ellipsis state
#if BOOST_PP_IS_SELFISH
#define ELLIPSIS_I ((true), (...))
#else
#define ELLIPSIS_I ((false), BOOST_PP_NIL)
#endif
#define N BOOST_PP_ITERATION()
template&lt;class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)&gt;
struct function_traits&lt;R (BOOST_PP_ENUM_PARAMS(N, T) ELLIPSIS(1))&gt;
: detail::function_traits_base {
static const bool is_plain = true;
typedef R function_type(BOOST_PP_ENUM_PARAMS(N, T) ELLIPSIS(1));
typedef function_type* pointer_type;
typedef function_type&amp; reference_type;
static const bool has_ellipsis = ELLIPSIS(0);
typedef R return_type;
static const int parameter_count = N;
template&lt;int, class D = int&gt; struct parameter;
#if N
// iterate over parameters
#define BOOST_PP_ITERATION_PARAMS_2 \
(3, (0, N - 1, "function_traits.hpp")) \
/**/
??=include BOOST_PP_ITERATE()
#endif
};
#undef N
#undef ELLIPSIS_I
// re-include this section for an ellipsis variant
#if !BOOST_PP_IS_SELFISH
#define BOOST_PP_INDIRECT_SELF "function_traits.hpp"
??=include BOOST_PP_INCLUDE_SELF()
#endif
// iteration over cv-qualifiers
#elif BOOST_PP_ITERATION_DEPTH() == 1 \
&amp;&amp; BOOST_PP_ITERATION_FLAGS() == 1 \
/**/
#define BOOST_PP_ITERATION_PARAMS_2 \
(3, (0, FUNCTION_TRAITS_MAX_ARITY, "function_traits.hpp")) \
/**/
??=include BOOST_PP_ITERATE()
// generate specializations for pointers-to-members
#elif BOOST_PP_ITERATION_DEPTH() == 2 \
&amp;&amp; BOOST_PP_FRAME_FLAGS(1) == 1 \
// define ellipsis state
#if BOOST_PP_IS_SELFISH
#define ELLIPSIS_I ((true), (...))
#else
#define ELLIPSIS_I ((false), BOOST_PP_NIL)
#endif
#define N BOOST_PP_ITERATION()
#define Q QUALIFIER(BOOST_PP_FRAME_ITERATION(1))
template&lt;class R, class O BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)&gt;
struct function_traits&lt;R (O::*)(BOOST_PP_ENUM_PARAMS(N, T) ELLIPSIS(1)) Q&gt;
: detail::function_traits_base {
static const bool is_member = true;
typedef R (O::* pointer_to_member_type)(BOOST_PP_ENUM_PARAMS(N, T) ELLIPSIS(1)) Q;
typedef O class_type;
typedef Q O qualified_class_type;
static const bool has_ellipsis = ELLIPSIS(0);
static const bool is_const =
BOOST_PP_FRAME_ITERATION(1) == 1 || BOOST_PP_FRAME_ITERATION(1) == 3;
static const bool is_volatile =
BOOST_PP_FRAME_ITERATION(1) == 2 || BOOST_PP_FRAME_ITERATION(1) == 3;
typedef R return_type;
static const int parameter_count = N;
template&lt;int, class D = int&gt; struct parameter;
#if N
// iterate over parameters
#define BOOST_PP_ITERATION_PARAMS_3 \
(3, (0, N - 1, "function_traits.hpp")) \
/**/
??=include BOOST_PP_ITERATE()
#endif
};
#undef Q
#undef N
#undef ELLIPSIS_I
// re-include this section for an ellipsis variant
#if !BOOST_PP_IS_SELFISH
#define BOOST_PP_INDIRECT_SELF "function_traits.hpp"
??=include BOOST_PP_INCLUDE_SELF()
#endif
// parameter specializations
#else
#define X BOOST_PP_ITERATION()
template&lt;class D&gt; struct parameter&lt;X, D&gt; {
typedef BOOST_PP_CAT(T, X) type;
};
#undef X
#endif
</pre></div>
<div>
One problem that still exists is the lack of support for <code>throw</code> specifications.&nbsp;
There is no way that we can completely handle it anyway because we cannot partially specialize
on <code>throw</code> specifications.&nbsp;
However, we could accurately report the "actual" function type, etc., including the <code>throw</code>
specification (which the above implementation doesn't do, as it reconstructs those types).&nbsp;
If you like, you can figure out how to do that on your own as an exercise.&nbsp;
</div>
<!--<h4>Related Topics</h4>
<ul>
<li><a href="choosing_repetition.html">Choosing Between Repetition Constructs</a></li>
</ul>-->
<h4>See Also</h4>
<ul>
<li><a href="../ref/iterate.html">BOOST_PP_ITERATE</a></li>
</ul>
<div class="sig">- Paul Mensonides</div>
</body>
</html>

View File

@ -0,0 +1,129 @@
<html>
<head>
<title>incompatible.html</title>
<link rel="stylesheet" type="text/css" href="../styles.css">
</head>
<body>
<h4>Incompatibilities</h4>
<div>
There are several incompatibilities with the previous Boost release (1.28).&nbsp;
These fall into roughly three categories:&nbsp;
</div>
<ul>
<li>the horizontal repetition primitives based on <b>BOOST_PP_REPEAT</b></li>
<li>the reentrancy syntax</li>
<li><i>list</i> folding</li>
</ul>
<h4>Repetition Targets</h4>
<div>
First, and probably the most commonly used, is the target macros passed into <b>BOOST_PP_REPEAT</b> and the horizontal repetition contructs that use <b>BOOST_PP_REPEAT</b>.&nbsp;
This includes all of the <b>BOOST_PP_REPEAT_</b>* primitives and all of the <b>BOOST_PP_ENUM_</b>* primitives that require a target macro.
</div>
<div>
The incompatiblity is trivial, but it will require that the source be updated.&nbsp;
</div>
<div>
These target macros must now except a <i>third</i> parameter.&nbsp;
This extra parameter becomes the <i>first</i> parameter in every target macro.&nbsp;
It represents the next repetition dimension and brings <b>BOOST_PP_REPEAT</b> inline with rest of the library.&nbsp;
</div>
<div>
So, what once was:
</div>
<div class="code">
#define <i>macro</i>(<i>n</i>, <i>data</i>) ...<br>
<b>BOOST_PP_REPEAT</b>(<i>5</i>, <i>macro</i>, <i>data</i>)
</div>
<div>
...is now:
</div>
<div class="code">
#define <i>macro</i>(<i>z</i>, <i>n</i>, <i>data</i>) ...<br>
<b>BOOST_PP_REPEAT</b>(<i>5</i>, <i>macro</i>, <i>data</i>)
</div>
<div>
This parameter can be used for highly efficient reentrance into the <b>BOOST_PP_REPEAT</b> mechanism.&nbsp;
However, it is not necessary to use it as the library can automatically detect the next available repetition dimension.
</div>
<h4>Dimensional Ordering</h4>
<div>
Because of this detection, however, it is unsafe to use <b>BOOST_PP_REPEAT_1ST</b>, <b>BOOST_PP_REPEAT_2ND</b>, and <b>BOOST_PP_REPEAT_3RD</b> out of order.&nbsp;
These macros bypass the <i>automatic-recursion</i> mechanism, and the <i>automatic-recursion</i> mechanism relies on macros being used in the proper order.&nbsp;
To clarify, if you use these bypass macros, the outer-most repetition <i>must</i> be <b>BOOST_PP_REPEAT_1ST</b>, then <b>BOOST_PP_REPEAT_2ND</b>, and finally <b>BOOST_PP_REPEAT_3RD</b>.&nbsp;
Any other usage is not supported by the library.&nbsp;
Sometimes it may work, and other times it won't.
</div>
<h4>Reentrancy Syntax</h4>
<div>
<i>Automatic-recursion</i> brings with it another issue as well.&nbsp;Previously, the reentrancy syntax for <b>BOOST_PP_WHILE</b> (and similarly for <b>BOOST_PP_FOR</b>) was:
</div>
<div class="code">
<b>BOOST_PP_WHILE</b> ## <i>d</i>(<i>pred</i>, <i>op</i>, <i>state</i>)
</div>
<div>
...or:
</div>
<div class="code">
<b>BOOST_PP_CAT</b>(<b>BOOST_PP_WHILE</b>, <i>d</i>)(<i>pred</i>, <i>op</i>, <i>state</i>)
</div>
<div>
Under the <i>automatic-recursion</i> model, the <b>BOOST_PP_CAT</b> version breaks.&nbsp;
This is because <b>BOOST_PP_CAT</b> allows its arguments to expand prior to concatenation,
and <b>BOOST_PP_WHILE</b> is a macro that expands without arguments.&nbsp;
The library makes it appear that it takes three parameters, but that is the trick of <i>automatic-recursion</i>.&nbsp;
It works similarly to the following:
</div>
<div class="code">
#define A(x, y) ...<br>
#define B A<br>
// ...<br>
B(2, 3)
</div>
<div>
The syntax makes it look like the <i>B</i> macro above takes two arguments, but it doesn't.&nbsp;
The <i>automatic-recursion</i> mechanism works in this fashion, except that the "<i>B</i>" macro deduces the next available "<i>A</i>" macro.
</div>
<div>
Because some preprocessors are still slow, direct reentrancy (sans <i>automatic-recursion</i>) is still necessary in non-trivial cases.&nbsp;
Consequently, the library uses a new syntax to handle reentrancy:
</div>
<div class="code">
<b>BOOST_PP_FOR_</b> ## <i>r</i>(<i>state</i>, <i>pred</i>, <i>op</i>, <i>macro</i>)<br>
<b>BOOST_PP_REPEAT_</b> ## <i>z</i>(<i>count</i>, <i>macro</i>, <i>data</i>)<br>
<b>BOOST_PP_WHILE_</b> ## <i>d</i>(<i>pred</i>, <i>op</i>, <i>state</i>)
</div>
<h4>Folding</h4>
<div>
Previously, the <b>BOOST_PP_LIST_FOLD_RIGHT</b> macros' arguments were the reverse of <b>BOOST_PP_LIST_FOLD_LEFT</b>.&nbsp;
Also, the accumulation macro passed into <b>BOOST_PP_LIST_FOLD_RIGHT</b> was called with reversed parameters as well.&nbsp;
This discrepancy has been eliminated.
</div>
<div>
To illustrate, <b>BOOST_PP_LIST_FOLD_RIGHT</b> used to be used like this:
</div>
<div class="code">
#define <i>macro</i>(<i>d</i>, <u><i>elem</i></u>, <u><i>state</i></u>)<br>
<b>BOOST_PP_LIST_FOLD_RIGHT</b>(<i>macro</i>, <u><i>list</i></u>, <u><i>state</i></u>)
</div>
<div>
This signature has been replaced by...
</div>
<div class="code">
#define <i>macro</i>(<i>d</i>, <u><i>state</i></u>, <u><i>elem</i></u>)<br>
<b>BOOST_PP_LIST_FOLD_RIGHT</b>(<i>macro</i>, <u><i>state</i></u>, <u><i>list</i></u>)
</div>
<h4>Summary</h4>
<div>
The library has many new features not present in the 1.28 release, and this list does not attempt to enumerate them.&nbsp;
This is simply a list of things that <i>must</i> change for code to be compatible with this new release.
</div>
<h4>See Also</h4>
<ul>
<li><a href="../ref/for.html">BOOST_PP_FOR</a></li>
<li><a href="../ref/list_fold_right.html">BOOST_PP_LIST_FOLD_RIGHT</a></li>
<li><a href="../ref/repeat.html">BOOST_PP_REPEAT</a></li>
<li><a href="../ref/while.html">BOOST_PP_WHILE</a></li>
</ul>
<div class="sig">- Paul Mensonides</div>
</body>
</html>

View File

@ -0,0 +1,149 @@
<html>
<head>
<title>local_iteration.html</title>
<link rel="stylesheet" type="text/css" href="../styles.css">
</head>
<body>
<h4>Local Iteration</h4>
<div>
Local iteration is a simple vertical repetition construct.&nbsp;
It expands a macro with each number in a user-specified range.&nbsp;
Each expansion is on a separate line.
</div>
<h4>Tutorial</h4>
<div>
This mechanism requires two pieces of information to operate:&nbsp;
a range to iterate over and a macro to expand on each iteration.&nbsp;
This information is obtained by the mechanism through two <i>named external arguments</i>.&nbsp;
These arguments are specified as user-defined macros named <b>BOOST_PP_LOCAL_LIMITS</b> and <b>BOOST_PP_LOCAL_MACRO</b>.
</div>
<div>
<b>BOOST_PP_LOCAL_LIMITS</b> specifies a range of values to iterate over.&nbsp;
It <i>must</i> expand to a <i>tuple</i> containing two elements--a lower and upper bound.&nbsp;
Both the upper and lower bounds must be numeric values in the range of <i>0</i> to <b>BOOST_PP_LIMIT_ITERATION</b>.&nbsp;
For example, if the user wishes a macro to be expanded with numbers ranging from <i>0</i> to <i>10</i>,
<b>BOOST_PP_LOCAL_LIMITS</b> would be defined like this:
</div>
<div class="code"><pre>
#define BOOST_PP_LOCAL_LIMITS (0, 10)
</pre></div>
<div>
Note that there is whitespace after the name of the macro.&nbsp;
The macro <i>does not</i> take <i>two</i> arguments.&nbsp;
In the case above, if there was no whitespace, a preprocessing error would occur because <i>0</i> and <i>10</i> are invalid identifiers.
</div>
<div>
Both the upper and lower bounds specified in the <b>BOOST_PP_LOCAL_LIMITS</b> macro are <i>evaluated parameters</i>.&nbsp;
This implies that they can include simple arithmetic or logical expressions.&nbsp;
For instance, the above definition could easily have been written like this:
</div>
<div class="code"><pre>
#define N() 5
#define BOOST_PP_LOCAL_LIMITS (0, N() + 5)
</pre></div>
<div>
Because of this, if the whitespace after the macro name is elided, it is possible for the definition to be syntactically valid:
</div>
<div class="code"><pre>
#define A 0
#define B 10
#define BOOST_PP_LOCAL_LIMITS(A, B)
// note: no whitespace ^
</pre></div>
<div>
If this happens, an error will occur inside the mechanism when it attempts to use this macro.&nbsp;
The error messages that result may be obscure, so always remember to include the whitespace.&nbsp;
A <i>correct</i> version of the above looks like this:
</div>
<div class="code"><pre>
#define A 0
#define B 10
#define BOOST_PP_LOCAL_LIMITS (A, B)
// note: has whitespace ^
</pre></div>
<div>
<b>BOOST_PP_LOCAL_MACRO</b> is the macro that is expanded by the mechanism.&nbsp;
This macro is expanded on each iteration with the current number of the iteration.&nbsp;
It must defined as a unary macro <i>or</i> result in a macro that can be called with one argument:
</div>
<div class="code"><pre>
#define BOOST_PP_LOCAL_MACRO(n) \
template&lt;&gt; struct sample&lt;n&gt; { }; \
/**/
</pre></div>
<div>
...or...
</div>
<div class="code"><pre>
#define SAMPLE(n) \
template&lt;&gt; struct sample&lt;n&gt; { }; \
/**/
#define BOOST_PP_LOCAL_MACRO SAMPLE
</pre></div>
<div>
Once these two macros are defined, the local iteration is initiated by <i>including</i> <b>BOOST_PP_LOCAL_ITERATE</b>().
</div>
<div class="code"><pre>
??=include BOOST_PP_LOCAL_ITERATE()
</pre></div>
<div>
(The <code>??=</code> token is a trigraph for <code>#</code>.&nbsp;
I use the trigraph to make it clear that I am <i>including</i> a file rather than defining or expanding a macro, but it is not necessary.&nbsp;
Even the digraph version, <code>%:</code>, could be used.&nbsp;
Some compilers do not readily accept trigraphs and digraphs, so keep that in mind.&nbsp;
Other than that, use whichever one you prefer.)
</div>
<div>
In order to repeat the <code>sample</code> specialization, the pieces must be put together....
</div>
<div class="code"><pre>
#define BOOST_PP_LOCAL_MACRO(n) \
template&lt;&gt; struct sample&lt;n&gt; { }; \
/**/
#define BOOST_PP_LOCAL_LIMITS (0, 10)
??=include BOOST_PP_LOCAL_ITERATE()
</pre></div>
<div>
This will result in a specialization of <code>sample</code> for each number in the range of <i>0</i> to <i>10</i>.&nbsp;
The output will look something like this:
</div>
<div class="code"><pre>
template&lt;&gt; struct sample&lt;0&gt; { };
template&lt;&gt; struct sample&lt;1&gt; { };
template&lt;&gt; struct sample&lt;2&gt; { };
// ...
template&lt;&gt; struct sample&lt;10&gt; { };
</pre></div>
<div>
After the local-iteration is complete, both <b>BOOST_PP_LOCAL_LIMITS</b> and <b>BOOST_PP_LOCAL_MACRO</b> are automatically undefined.&nbsp;
If the values need to be retained for a future local-iteration, they must be defined indirectly:
</div>
<div class="code"><pre>
#define LIMITS (0, 10)
#define SAMPLE(n) \
template&lt;&gt; struct sample&lt;n&gt; { }; \
/**/
#define BOOST_PP_LOCAL_LIMITS LIMITS
#define BOOST_PP_LOCAL_MACRO(n) SAMPLE(n)
??=include BOOST_PP_LOCAL_ITERATE()
</pre></div>
<!--<h4>Related Topics</h4>
<ul>
<li><a href="choosing_repetition.html">Choosing Between Repetition Constructs</a></li>
</ul>-->
<h4>See Also</h4>
<ul>
<li><a href="../ref/local_iterate.html">BOOST_PP_LOCAL_ITERATE</a></li>
<li><a href="../ref/local_limits.html">BOOST_PP_LOCAL_LIMITS</a></li>
<li><a href="../ref/local_macro.html">BOOST_PP_LOCAL_MACRO</a></li>
</ul>
<div class="sig">- Paul Mensonides</div>
</body>
</html>

100
doc/topics/motivation.html Normal file
View File

@ -0,0 +1,100 @@
<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.&nbsp;
This leads to unnecessary code repetition.
</div>
<div>
Consider the implementation of the <code>is_function&lt;&gt;</code> metafunction is Boost.&nbsp;
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.&nbsp;
Because of the special treatment of parameter lists, it is not possible to directly match a function with an arbitrary parameter list.&nbsp;
Instead, the <code>is_function_tester()</code> must be overloaded for every distinct number of parameters that is to be supported.&nbsp;
For example:
</div>
<div class="code"><pre>
template&lt;class R&gt;
yes_type is_function_tester(R (*)());
template&lt;class R, class A0&gt;
yes_type is_function_tester(R (*)(A0));
template&lt;class R, class A0, class A1&gt;
yes_type is_function_tester(R (*)(A0, A1));
template&lt;class R, class A0, class A1, class A2&gt;
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.&nbsp;
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.&nbsp;
Unfortunately, using external code generators has many disadvantages:
<ul>
<li>Writing the generator takes time.&nbsp; (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.&nbsp; (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.&nbsp;
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.&nbsp;
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>
#define IS_FUNCTION_TESTER(Z, N, _) \
template&lt;class R BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_PARAMS(N, class A)&gt; \
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.&nbsp;
This document is provided "as is" without express or implied warranty and with no claim as to its suitability for any purpose.
</div>
</body>
</html>

124
doc/topics/problems.html Normal file
View File

@ -0,0 +1,124 @@
<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.&nbsp;
Part of this is caused by bad experiences with dangerous techniques,
such as defining inline functions using macros.&nbsp;
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.&nbsp;
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.&nbsp;
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.&nbsp;
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.&nbsp;
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.&nbsp;
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.&nbsp;
The work bottom-up, replacing hand-written constructs by using the preprocessor.&nbsp;
This way you can test the code incrementally.&nbsp;
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.&nbsp;
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><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.&nbsp;
This document is provided "as is" without express or implied warranty and with no claim as to its suitability for any purpose.
</div>
</body>
</html>

253
doc/topics/reentrancy.html Normal file
View File

@ -0,0 +1,253 @@
<html>
<head>
<title>reentrancy.html</title>
<link rel="stylesheet" type="text/css" href="../styles.css">
</head>
<body>
<h4>Reentrancy</h4>
<div>
Macro expansion in the preprocessor is entirely functional.&nbsp;
Therefore, there is no iteration.&nbsp;
Unfortunately, the preprocessor also disallows recursion.&nbsp;
This means that the library must fake iteration or recursion by
defining sets of macros that are implemented similarly.&nbsp;
</div>
<div>
To illustrate, here is a simple concatenation macro:
</div>
<div class="code"><pre>
#define CONCAT(a, b) CONCAT_D(a, b)
#define CONCAT_D(a, b) a ## b
CONCAT(a, CONCAT(b, c)) // abc
</pre></div>
<div>
This is fine for a simple case like the above, but what happens in a scenario like the following:
</div>
<div class="code"><pre>
#define AB(x, y) CONCAT(x, y)
CONCAT(A, B(p, q)) // CONCAT(p, q)
</pre></div>
<div>
Because there is no recursion, the example above expands to <code>CONCAT(p, q)</code> rather than <code>pq</code>.
</div>
<div>
There are only two ways to "fix" the above.&nbsp;
First, it can be documented that <code>AB</code> uses <code>CONCAT</code> and disallow usage similar to the above.&nbsp;
Second, multiple concatenation macros can be provided....
</div>
<div class="code"><pre>
#define CONCAT_1(a, b) CONCAT_1_D(a, b)
#define CONCAT_1_D(a, b) a ## b
#define CONCAT_2(a, b) CONCAT_2_D(a, b)
#define CONCAT_2_D(a, b) a ## b
#define AB(x, y) CONCAT_2(x, y)
CONCAT_1(A, B(p, q)) // pq
</pre></div>
<div>
This solves the problem.&nbsp;
However, it is now necessary to know that <code>AB</code> uses, not only <i>a</i> concatenation macro,
but <code>CONCAT_2</code> specifically.
</div>
<div>
A better solution is to abstract <i>which</i> concatenation macro is used....
</div>
<div class="code"><pre>
#define AB(c, x, y) CONCAT_ ## c(x, y)
CONCAT_1(A, B(2, p, q)) // pq
</pre></div>
<div>
This is an example of <i>generic reentrance</i>, in this case, into a fictional set of concatenation macros.&nbsp;
The <code>c</code> parameter represents the "state" of the concatenation construct,
and as long as the user keeps track of this state, <code>AB</code> can be used inside of a concatenation macro.
</div>
<div>
The library has the same choices.&nbsp;
It either has to disallow a construct being inside itself or provide multiple, equivalent definitions of a construct
and provide a uniform way to <i>reenter</i> that construct.&nbsp;
There are several contructs that <i>require</i> recursion (such as <b>BOOST_PP_WHILE</b>).&nbsp;
Consequently, the library chooses to provide several sets of macros with mechanisms to reenter the set at a macro
that has not already been used.
</div>
<div>
In particular, the library must provide reentrance for <b>BOOST_PP_FOR</b>, <b>BOOST_PP_REPEAT</b>, and <b>BOOST_PP_WHILE</b>.&nbsp;
There are two mechanisms that are used to accomplish this:&nbsp; state parameters (like the above concatenation example) and <i>automatic recursion</i>.
</div>
<h4>State Parameters</h4>
<div>
Each of the above constructs (<b>BOOST_PP_FOR</b>, <b>BOOST_PP_REPEAT</b>, and <b>BOOST_PP_WHILE</b>) has an associated state.&nbsp;
This state provides the means to reenter the respective construct.
</div>
<div>
Several user-defined macros are passed to each of these constructs (for use as predicates, operations, etc.).&nbsp;
Every time a user-defined macro is invoked, it is passed the current state of the construct that invoked it so that the macro can reenter
the respective set if necessary.
</div>
<div>
These states are used in one of two ways--either by concatenating to or passing to another macro.
</div>
<div>
There are three types of macros that use these state parameters.&nbsp;
First, the set itself which is reentered through concatenation.&nbsp;
Second, corresponding sets that act like they are a part of the the primary set.&nbsp;
These are also reentered through concatenation.&nbsp;
And third, macros that internally use the first or second type of macro.&nbsp;
These macros take the state as an additional argument.
</div>
<div>
The state of <b>BOOST_PP_WHILE</b> is symbolized by the letter <i>D</i>.&nbsp;
Two user-defined macros are passed to <b>BOOST_PP_WHILE</b>--a predicate and an operation.&nbsp;
When <b>BOOST_PP_WHILE</b> expands these macros, it passes along its state so that these macros
can reenter the <b>BOOST_PP_WHILE</b> set.&nbsp;
</div>
<div>
Consider the following multiplication implementation that illustrates this technique:
</div>
<div class="code"><pre>
// The addition interface macro.
// The _D signifies that it reenters
// BOOST_PP_WHILE with concatenation.
#define ADD_D(d, x, y) \
BOOST_PP_TUPLE_ELEM( \
2, 0, \
BOOST_PP_WHILE_ ## d(ADD_P, ADD_O, (x, y)) \
) \
/**/
// The predicate that is passed to BOOST_PP_WHILE.
// It returns "true" until "y" becomes zero.
#define ADD_P(d, xy) BOOST_PP_TUPLE_ELEM(2, 1, xy)
// The operation that is passed to BOOST_PP_WHILE.
// It increments "x" and decrements "y" which will
// eventually cause "y" to equal zero and therefore
// cause the predicate to return "false."
#define ADD_O(d, xy) \
( \
BOOST_PP_INC( \
BOOST_PP_TUPLE_ELEM(2, 0, xy) \
), \
BOOST_PP_DEC( \
BOOST_PP_TUPLE_ELEM(2, 1, xy) \
) \
) \
/**/
// The multiplication interface macro.
#define MUL(x, y) \
BOOST_PP_TUPLE_ELEM( \
3, 0, \
BOOST_PP_WHILE(MUL_P, MUL_O, (0, x, y)) \
) \
/**/
// The predicate that is passed to BOOST_PP_WHILE.
// It returns "true" until "y" becomes zero.
#define MUL_P(d, rxy) BOOST_PP_TUPLE_ELEM(3, 2, rxy)
// The operation that is passed to BOOST_PP_WHILE.
// It adds "x" to "r" and decrements "y" which will
// eventually cause "y" to equal zero and therefore
// cause the predicate to return "false."
#define MUL_O(d, rxy) \
( \
ADD_D( \
d, /* pass the state on to ADD_D */ \
BOOST_PP_TUPLE_ELEM(3, 0, rxy), \
BOOST_PP_TUPLE_ELEM(3, 1, rxy) \
), \
BOOST_PP_TUPLE_ELEM(3, 1, rxy), \
BOOST_PP_DEC( \
BOOST_PP_TUPLE_ELEM(3, 2, rxy) \
) \
) \
/**/
MUL(3, 2) // expands to 6
</pre></div>
<div>
There are a couple things to note in the above implementation.&nbsp;
First, note how <code>ADD_D</code> reenters <b>BOOST_PP_WHILE</b> using the <i>d</i> state parameter.&nbsp;
Second, note how <code>MUL</code>'s operation, which is expanded by <b>BOOST_PP_WHILE</b>, passes the state
on to <code>ADD_D</code>.&nbsp;
This illustrates state reentrance by both argument and concatenation.
</div>
<div>
For every macro in the library that uses <b>BOOST_PP_WHILE</b>,
there is a state reentrant variant.&nbsp;
If that variant uses an argument rather than concatenation, it is suffixed by <code>_D</code> to symbolize its
method of reentrance.&nbsp;
Examples or this include the library's own <b>BOOST_PP_ADD_D</b> and <b>BOOST_PP_MUL_D</b>.&nbsp;
If the variant uses concatenation, it is suffixed by an underscore.&nbsp;
It is completed by concatenation of the state.&nbsp;
This includes <b>BOOST_PP_WHILE</b> itself with <b>BOOST_PP_WHILE_</b> ## <i>d</i> and, for example,
<b>BOOST_PP_LIST_FOLD_LEFT</b> with <b>BOOST_PP_LIST_FOLD_LEFT_</b> ## <i>d</i>.
</div>
<div>
The same set of conventions are used for <b>BOOST_PP_FOR</b> and <b>BOOST_PP_REPEAT</b>, but with the letters
<i>R</i> and <i>Z</i>, respectively, to symbolize their states.
</div>
<div>
Also note that the above <code>MUL</code> implementation, though not immediately obvious, is using <i>all three</i>
types of reentrance.&nbsp;
Not only is it using both types of <i>state</i> reentrance, it is also using <i>automatic recursion</i>....
</div>
<h4>Automatic Recursion</h4>
<div>
Automatic recursion is a technique that vastly simplifies the use of reentrant constructs.&nbsp;
It is used by simply <i>not</i> using any state parameters at all.
</div>
<div>
The <code>MUL</code> example above uses automatic recursion when it uses <b>BOOST_PP_WHILE</b> by itself.&nbsp;
In other words, <code>MUL</code> can <i>still</i> be used inside <b>BOOST_PP_WHILE</b> even though it doesn't
reenter <b>BOOST_PP_WHILE</b> by concatenating the state to <b>BOOST_PP_WHILE_</b>.
</div>
<div>
To accomplish this, the library uses a "trick."&nbsp;
Despite what it looks like, the macro <b>BOOST_PP_WHILE</b> does not take three arguments.&nbsp;
In fact, it takes no arguments at all.&nbsp;
Instead, the <b>BOOST_PP_WHILE</b> macro expands <i>to</i> a macro that takes three arguments.&nbsp;
It simply detects what the next available <b>BOOST_PP_WHILE_</b> ## <i>d</i> macro is and returns it.&nbsp;
This detection process is somewhat involved, so I won't go into <i>how</i> it works here,
but suffice to say it <i>does</i> work.
</div>
<div>
Using automatic recursion to reenter various sets of macros is obviously much simpler.&nbsp;
It completely hides the underlying implementation details.&nbsp;
So, if it is so much easier to use, why do the state parameters still exist?&nbsp;
The reason is simple as well.&nbsp;
When state parameters are used, the state is <i>known</i> at all times.&nbsp;
This is not the case when automatic recursion is used.&nbsp;
The automatic recursion mechanism has to <i>deduce</i> the state at each point that it is used.&nbsp;
This implies a cost in macro complexity that in some situations--notably at deep macro depths--will slow
some preprocessors to a crawl.
</div>
<h4>Conclusion</h4>
<div>
It is really a tradeoff whether to use state parameters or automatic recursion for reentrancy.&nbsp;
The strengths of automatic recursion are ease of use and implementation encapsulation.&nbsp;
These come at a performance cost on some preprocessors in some situations.&nbsp;
The primary strength of state parameters, on the other hand, is efficiency.&nbsp;
Use of the state parameters is the only way to achieve <i>maximum</i> efficiency.&nbsp;
This efficiency comes at the cost of both code complexity and exposition of implementation.
</div>
<h4>See Also</h4>
<ul>
<li><a href="../ref/for.html">BOOST_PP_FOR</a></li>
<li><a href="../ref/repeat.html">BOOST_PP_REPEAT</a></li>
<li><a href="../ref/while.html">BOOST_PP_WHILE</a></li>
</ul>
<div class="sig">- Paul Mensonides</div>
</body>
</html>

336
doc/topics/techniques.html Normal file
View File

@ -0,0 +1,336 @@
<html>
<head>
<title>techniques.html</title>
<link rel="stylesheet" type="text/css" href="../styles.css">
<style>
u { font-weight: normal; text-decoration: none; }
</style>
</head>
<body>
<h4>Techniques</h4>
<div>
The preprocessor metaprogramming techniques are presented in example format.
</div>
<h4>Example<u> - Use a local macro to avoid small scale repetition.</u></h4>
<div class="code"><pre>
#define BOOST_PP_DEF(op) /* ..................................... */ \
template&lt;class T, int n&gt; \
vec&lt;T, n&gt; operator op ## =(vec&lt;T, n&gt; lhs, const vec&lt;T, n&gt;& rhs) { \
for (int i = 0; i &lt; n; ++i) { \
lhs(i) op ## = rhs(i); \
} \
} \
/**/
BOOST_PP_DEF(+)
BOOST_PP_DEF(-)
BOOST_PP_DEF(*)
BOOST_PP_DEF(/)
#undef BOOST_PP_DEF
</pre></div>
<div>
<b>Tip:</b>&nbsp; It is usually okay to use a standard macro name like <code>BOOST_PP_DEF</code> for this kind of code
because the macro is both defined and undefined in the immediate site of its use.
</div>
<div>
<b>Tip:</b>&nbsp; It is easier to verify proper use of the line continuation operator when they are aligned.
</div>
<div>
<b>Notes:</b>&nbsp; You can extend this example by defining more and different kinds of operators.&nbsp;
Before doing so, consider using the <i>algebraic categories</i> technique introduced in <a href="bibliography.html#barton">[Barton]</a>
or a <i>layered architecture</i> (see for instance <a href="bibliography.html#czarnecki">[Czarnecki]</a>).&nbsp;
However, at some point you must type the operator tokens <code>*</code>, <code>/</code>, <code>+</code>, <code>-</code>, etc.,
because it is impossible to generate them using templates.&nbsp;
The resulting <i>categorical repetition</i> of tokens can be eliminated by using preprocessor metaprogramming.
</div>
<h4>Example<u> - Use BOOST_PP_EMPTY as an unused parameter in local macro instantiations.</u></h4>
<div class="code"><pre>
#define BOOST_PP_DEF(cv) /* ... */ \
template&lt;class base&gt; \
cv() typename implement_subscript_using_begin_subscript&lt;base&gt;::value_type& \
implement_subscript_using_begin_subscript&lt;base&gt;::operator[](index_type i) cv() { \
return base::begin()[i]; \
} \
/**/
</pre></div>
<div>
<b>How:</b>&nbsp; BOOST_PP_EMPTY() expands to nothing and can be used as an unused parameter.
</div>
<div>
<b>Note:</b>&nbsp; BOOST_PP_EMPTY with the () never gets expanded.&nbsp;
The () is necessary to invoke a function-like macro.
</div>
<div>
<b>Caveat:</b>&nbsp; You cannot safely use concatenation while using BOOST_PP_EMPTY().
</div>
<div>
<b>Tip:</b>&nbsp; Occasionally, one or two lines are considerably longer than the rest.&nbsp;
It can often save some work to <i>not</i> align all the line continuation operators without making the code too unreadable.
</div>
<div>
<b>Tip:</b>&nbsp; Use syntax highlighting on preprocessor metaprogramming macro identifiers such as:
<ul>
<li>BOOST_PP_DEF</li>
<li>BOOST_PP_EMPTY</li>
<li>BOOST_PP_REPEAT</li>
<li>...</li>
</ul>
It can greatly improve readability.
</div>
<h4>Example<u> - Use BOOST_PP_CAT instead of ## when necessary.</u></h4>
<div class="code"><pre>
#define STATIC_ASSERT(expr) \
enum { BOOST_PP_CAT(static_check_, __LINE__) = (expr) ? 1 : -1 }; \
typedef char \
BOOST_PP_CAT(static_assert_, __LINE__)[BOOST_PP_CAT(static_check_, __LINE__)] \
/**/
// ...
STATIC_ASSERT(sizeof(int) &lt;= sizeof(long));
</pre></div>
<div>
<b>Why:</b>&nbsp; Macro expansion proceeds recursively in "layers."&nbsp;
Token pasting prevents the preprocessor from performing macro expansion,
therefore it is often necessary to delay token concatenation.
</div>
<h4>Example<u> - Use BOOST_PP_STRINGIZE instead of # whenever necessary.</u></h4>
<div class="code"><pre>
#define NOTE(str) \
message(__FILE__ "(" BOOST_PP_STRINGIZE(__LINE__) ") : " str) \
/**/
// ...
#pragma NOTE("TBD!")
</pre></div>
<div>
<b>Why:</b>&nbsp; Macro expansion proceeds recursively in "layers."&nbsp;
Stringization prevents the preprocessor from performing macro expansion, therefore it is often necessary to delay stringization.
</div>
<h4>Example<u> - Use BOOST_PP_ENUM_PARAMS (and its variants) or BOOST_PP_REPEAT and BOOST_PP_COMMA_IF to avoid <i>O</i>(<i>n</i>) repetition on lists in general.</u></h4>
<div class="code"><pre>
struct make_type_list_end;
template&lt;
BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
MAKE_TYPE_LIST_MAX_LENGTH,
class T,
make_type_list_end
)
&gt;
struct make_type_list {
private:
enum { end = is_same&lt;T0, make_type_list_end&gt;::value };
public:
typedef typename type_if&lt;
end, type_cons_empty,
type_cons&lt;
T0,
typename type_inner_if&lt;
end, type_identity&lt;end&gt;,
make_type_list&lt;
BOOST_PP_ENUM_SHIFTED_PARAMS(
MAKE_TYPE_LIST_MAX_LENGTH,
T
)
&gt;
&gt;::type
&gt;
&gt;::type type;
};
</pre></div>
<div>
<b>How:</b>&nbsp; BOOST_PP_REPEAT uses simulated recursion (pseudo code):
</div>
<div><pre>
#define BOOST_PP_REPEAT(n, m, p) BOOST_PP_REPEAT ## n(m, p)
#define BOOST_PP_REPEAT0(m, p)
#define BOOST_PP_REPEAT1(m, p) m(0, p)
#define BOOST_PP_REPEAT2(m, p) m(0, p) m(1, p)
#define BOOST_PP_REPEAT3(m, p) BOOST_PP_REPEAT2(m, p) m(2, p)
#define BOOST_PP_REPEAT4(m, p) BOOST_PP_REPEAT3(m, p) m(3, p)
// ...
</pre></div>
<div>
<i>Note:&nbsp; This is no longer how BOOST_PP_REPEAT is implemented, so the code above is illustrative only!&nbsp;</i>
</div>
<div>
BOOST_PP_ENUM_PARAMS and its variations use BOOST_PP_REPEAT.&nbsp;
BOOST_PP_COMMA_IF(I) expands to a comma if I != 0.&nbsp;
BOOST_PP_INC(I) essentially expands to "I+1," and BOOST_PP_DEC(I) essentially expands to "I-1.".
</div>
<h4>Example<u> - Use a <i>conditional macro definition</i> to enable user configuration of code repetition based on need rather than some "reasonable" upper limit.</u></h4>
<div class="code"><pre>
#ifndef MAKE_TYPE_LIST_MAX_LENGTH
#define MAKE_TYPE_LIST_MAX_LENGTH 8
#endif
</pre></div>
<div>
Now the user can configure the <code>make_type_list</code> primitive without modifying library code.
</div>
<h4>Example<u> - Use BOOST_PP_REPEAT and a <i>token look-up function</i> to eliminate categorical repetition.</u></h4>
<div class="code"><pre>
// CAVEAT: My compiler is not standard on arithmetic types.
#define ARITHMETIC_TYPE(I) ARITHMETIC_TYPE ## I
#define ARITHMETIC_TYPE0 bool
#define ARITHMETIC_TYPE1 char
#define ARITHMETIC_TYPE2 signed char
#define ARITHMETIC_TYPE3 unsigned char
#define ARITHMETIC_TYPE4 short
#define ARITHMETIC_TYPE5 unsigned short
#define ARITHMETIC_TYPE6 int
#define ARITHMETIC_TYPE7 unsigned int
#define ARITHMETIC_TYPE8 long
#define ARITHMETIC_TYPE9 unsigned long
#define ARITHMETIC_TYPE10 float
#define ARITHMETIC_TYPE11 double
#define ARITHMETIC_TYPE12 long double
#define ARITHMETIC_TYPE_CNT 13
// ...
#define BOOST_PP_DEF(z, I, _) /* ... */ \
catch (ARITHMETIC_TYPE(I) t) { \
report_typeid(t); \
report_value(t); \
} \
/**/
BOOST_PP_REPEAT(ARITHMETIC_TYPE_CNT, BOOST_PP_DEF, _)
#undef BOOST_PP_DEF
</pre></div>
<div>
<b>Note:</b>&nbsp; The repetition of the above example can be eliminated using template metaprogramming <a href="bibliography.html#czarnecki">[Czarnecki]</a> as well.&nbsp;
However categorical repetition of operator tokens cannot be completely eliminated by using template metaprogramming.
</div>
<h4>Example<u> - Use BOOST_PP_REPEAT to avoid <i>O</i>(<i>n</i>*<i>n</i>) repetition.</u></h4>
<div class="code"><pre>
#ifndef MAX_VEC_ARG_CNT
#define MAX_VEC_ARG_CNT 8
#endif
// ...
#define ARG_FUN(z, i, _) BOOST_PP_COMMA_IF(i) T a ## i
#define ASSIGN_FUN(z, i, ) (*this)[i] = a ## i;
#define DEF_VEC_CTOR_FUN(z, i, _) /* ... */ \
vec(BOOST_PP_REPEAT(i, ARG_FUN, _)) { \
BOOST_PP_REPEAT(i, ASSIGN_FUN, _) \
} \
/**/
BOOST_PP_REPEAT(BOOST_PP_INC(MAX_VEC_ARG_CNT), DEF_VEC_CTOR_FUN, _)
#undef ARG_FUN
#undef ASSIGN_FUN
#undef DEF_VEC_CTOR_FUN
// ...
</pre></div>
<div>
<b>How:</b>&nbsp; BOOST_PP_REPEAT is implemented is a special way to enable <i>automatic recursion</i>.
</div>
<h4>Example<u> - Use BOOST_PP_IF to implement special case for the first element.</u></h4>
<div class="code"><pre>
#define COMMA_IF(c) \
BOOST_PP_IF(c, BOOST_PP_COMMA, BOOST_PP_EMPTY)() \
/**/
BOOST_PP_IF(0, true, false) == false;
BOOST_PP_IF(1, true, false) == true;
</pre></div>
<div>
BOOST_PP_IF enables convenient generation of lists using BOOST_PP_REPEAT.
</div>
<div>
<b>Note:</b>&nbsp; <i>THEN</i> and <i>ELSE</i> don't have to be macros.&nbsp;
However, if at least one of them is a function-like macro, and you want it be expanded conditionally,
you have to make the other parameter a function-like macro too.&nbsp;
This can often be done using BOOST_PP_IDENTITY.&nbsp;
Consider the following example (by Aleksey Gurtovoy):
</div>
<div><pre>
#define NUMBERED_EXPRESSION(i, x) /* ... */ \
BOOST_PP_IF( \
i, \
BOOST_PP_IDENTITY(x ## i) \
BOOST_PP_EMPTY \
)() \
/**/
</pre></div>
<div>
<b>Note:</b>&nbsp; Like in the above implementation of COMMA_IF, the result of BOOST_PP_IF is often invoked and not the <i>THEN</i> and <i>ELSE</i> parameters.&nbsp;
If the parameters were invoked, the code would not expand correctly, because the BOOST_PP_EMPTY parameter would get expanded
to nothing before the <b>BOOST_PP_IF</b> would be properly expanded.
</div>
<div>
<b>How:</b>&nbsp; BOOST_PP_IF is defined for the entire repeat range (psuedo code):
</div>
<div><pre>
#define BOOST_PP_IF(c, THEN, ELSE) BOOST_PP_IF ## c(THEN, ELSE)
#define BOOST_PP_IF0(THEN, ELSE) ELSE
#define BOOST_PP_IF1(THEN, ELSE) THEN
#define BOOST_PP_IF1(THEN, ELSE) THEN
// ...
</pre></div>
<h4>Example:<u>&nbsp; Use arithmetic, logical, and comparison operations when necessary.</u></h4>
<div class="code"><pre>
#define SPECIAL_NUMBERED_LIST(n, i, elem, special) \
BOOST_PP_ASSERT_MSG( \
BOOST_PP_LESS(i, n), \
bad params for SPECIAL_NUMBERED_LIST! \
) \
BOOST_PP_ENUM_PARAMS(i, elem) \
BOOST_PP_COMMA_IF(i) special \
BOOST_PP_REPEAT( \
BOOST_PP_SUB(BOOST_PP_DEC(n), i), \
SPECIAL_NUMBERED_LIST_HELPER, \
(elem, i) \
) \
/**/
#define SPECIAL_NUMBERED_LIST_HELPER(z, i, elem_base) \
, \
BOOST_PP_CAT( \
BOOST_PP_TUPLE_ELEM(2, 0, elem_base), \
BOOST_PP_ADD( \
i, \
BOOST_PP_TUPLE_ELEM(2, 1, elem_base) \
) \
) \
/**/
SPECIAL_NUMBERED_LIST(3, 0, E, S)
SPECIAL_NUMBERED_LIST(3, 1, E, S)
SPECIAL_NUMBERED_LIST(3, 2, E, S)
SPECIAL_NUMBERED_LIST(3, 3, E, S)
</pre></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.&nbsp;
This document is provided "as is" without express or implied warranty and with no claim as to its suitability for any purpose.
</div>
</body>
</html>