]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/preprocessor/doc/topics/file_iteration.html
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / preprocessor / doc / topics / file_iteration.html
CommitLineData
7c673cae
FG
1<html>
2 <head>
3 <title>file_iteration.html</title>
4 <link rel="stylesheet" type="text/css" href="../styles.css">
5 </head>
6 <body>
7 <h4>
8 File Iteration
9 </h4>
10 <div>
11 File iteration is a complex, but powerful, vertical repetition construct.&nbsp;
12 It repeatedly includes a <i>file</i> for each number in a user-specified range.
13 </div>
14 <h4>
15 Tutorial
16 </h4>
17 <div>
18 This mechanism requires two pieces of information to operate:&nbsp; a range to
19 iterate over and a file to include on each iteration.&nbsp; It can optionally
20 take a third piece of information that represents flags used to discriminate
21 between different iterations of the same file.&nbsp; This information is
22 obtained by the mechanism through one or two <i>named external arguments</i>.&nbsp;
23 These arguments are specified as user-defined macros named <b>BOOST_PP_ITERATION_PARAMS_<i>x</i></b>
24 or the combination of <b>BOOST_PP_FILENAME_<i>x</i></b> and <b>BOOST_PP_ITERATION_LIMITS</b>.
25 </div>
26 <div>
27 <b>BOOST_PP_ITERATION_LIMITS</b> specifies the range of values to iterate
28 over.&nbsp; It <i>must</i> expand to a <i>tuple</i> containing two elements--a
29 lower and upper bound.&nbsp; Both the upper and lower bounds must be numeric
30 values in the range of <i>0</i> to <b>BOOST_PP_LIMIT_ITERATION</b>.&nbsp; For
31 example, if the user wishes a file to be included for numbers ranging from <i>0</i>
32 to <i>10</i>, <b>BOOST_PP_ITERATION_LIMITS</b> would be defined like this:
33 </div>
34 <div class="code">
35 <pre>
36#define BOOST_PP_ITERATION_LIMITS (0, 10)
37</pre>
38 </div>
39 <div>
40 Note that there is whitespace after the name of the macro.&nbsp; The macro <i>does
41 not</i> take <i>two</i> arguments.&nbsp; In the case above, if there was
42 no whitespace, a preprocessing error would occur because <i>0</i> and <i>10</i>
43 are invalid identifiers.
44 </div>
45 <div>
46 Both the upper and lower bounds specified in the <b>BOOST_PP_ITERATION_LIMITS</b>
47 macro are <i>evaluated parameters</i>.&nbsp; This implies that they can include
48 simple arithmetic or logical expressions.&nbsp; For instance, the above
49 definition could easily have been written like this:
50 </div>
51 <div class="code">
52 <pre>
53#define N() 5
54#define BOOST_PP_ITERATION_LIMITS (0, N() + 5)
55</pre>
56 </div>
57 <div>
58 Because of this, if the whitespace after the macro name is elided, it is
59 possible for the definition to be syntactically valid:
60 </div>
61 <div class="code">
62 <pre>
63#define A 0
64#define B 10
65#define BOOST_PP_ITERATION_LIMITS(A, B)
66 // note: no whitespace ^
67</pre>
68 </div>
69 <div>
70 If this happens, an error will occur inside the mechanism when it attempts to
71 use this macro.&nbsp; The error messages that result may be obscure, so always
72 remember to include the whitespace.&nbsp; A <i>correct</i> version of the above
73 looks like this:
74 </div>
75 <div class="code">
76 <pre>
77#define A 0
78#define B 10
79#define BOOST_PP_ITERATION_LIMITS (A, B)
80 // note: has whitespace ^
81</pre>
82 </div>
83 <div>
84 <b>BOOST_PP_FILENAME_<i>x</i></b> specifies the file to iterate over.&nbsp; The <i>x</i>
85 is a placeholder for the dimension of iteration.&nbsp; (For now, we'll assume
86 this is <i>1</i>--i.e. the first dimension, so we are actually dealing with <b>BOOST_PP_FILENAME_1</b>.)&nbsp;
87 This macro must expand to a valid filename--in quotes or in angle brackets
88 depending on how the file is accessed:
89 </div>
90 <div class="code">
91 <pre>
92#define BOOST_PP_FILENAME_1 "file.h"
93// -or-
94#define BOOST_PP_FILENAME_1 &lt;file.h&gt;
95</pre>
96 </div>
97 <div>
98 All that we need now to perform a simple file iteration is to invoke the
99 mechanism:
100 </div>
101 <div class="code">
102 <pre>
103??=include BOOST_PP_ITERATE()
104</pre>
105 </div>
106 <div>
107 (The <code>??=</code> token is a trigraph for <code>#</code>.&nbsp; I use the
108 trigraph to make it clear that I am <i>including</i> a file rather than
109 defining or expanding a macro, but it is not necessary.&nbsp; Even the digraph
110 version, <code>%:</code>, could be used.&nbsp; Some compilers do not readily
111 accept trigraphs and digraphs, so keep that in mind.&nbsp; Other than that, use
112 whichever one you prefer.)
113 </div>
114 <div>
115 So, if we wish to iterate "file.h" from <i>1</i> to <i>10</i>, we just need to
116 put the pieces together:
117 </div>
118 <div class="code">
119 <pre>
120#define BOOST_PP_ITERATION_LIMITS (1, 10)
121#define BOOST_PP_FILENAME_1 "file.h"
122??=include BOOST_PP_ITERATE()
123</pre>
124 </div>
125 <div>
126 The above code has the effect of including "file.h" ten times in
127 succession.&nbsp;
128 </div>
129 <div>
130 Alternately, both the range and the file to iterate over can be expressed in
131 one macro, <b>BOOST_PP_ITERATION_PARAMS_<i>x</i></b>.&nbsp; Once again, the <i>x</i>
132 is a placeholder for the dimension of iteration--which we'll assume is <i>1</i>.&nbsp;
133 This macro must expand to an <i>array</i> that includes the lower bound, upper
134 bound, filename, and optional flags (in that order).
135 </div>
136 <div class="code">
137 <pre>
138#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 10, "file.h"))
139??=include BOOST_PP_ITERATE()
140</pre>
141 </div>
142 <div>
143 This has the same effect as the previous version.&nbsp; Only one of these two
144 ways to specify the parameters can be used at a time.&nbsp; (The reason that
145 there are two different methods has to do with dimensional abstraction which
146 I'll get to later.)
147 </div>
148 <div>
149 There is nothing particularly useful about including a file ten times.&nbsp;
150 The difference is that the current macro state changes each time.&nbsp; For
151 example, the current "iteration value" is available with <b>BOOST_PP_ITERATION</b>().&nbsp;
152 If "file.h" is defined like this...
153 </div>
154 <div class="code">
155 <pre>
156// file.h
157template&lt;&gt; struct sample&lt;BOOST_PP_ITERATION()&gt; { };
158</pre>
159 </div>
160 <div>
161 ...and it is iterated as follows...
162 </div>
163 <div class="code">
164 <pre>
165template&lt;int&gt; struct sample;
166
167#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 5, "file.h"))
168??=include BOOST_PP_ITERATE()
169</pre>
170 </div>
171 <div>
172 ...the result is different each time:
173 </div>
174 <div>
175 <pre>
176template&lt;&gt; struct sample&lt;1&gt; { };
177template&lt;&gt; struct sample&lt;2&gt; { };
178template&lt;&gt; struct sample&lt;3&gt; { };
179template&lt;&gt; struct sample&lt;4&gt; { };
180template&lt;&gt; struct sample&lt;5&gt; { };
181</pre>
182 </div>
183 <div>
184 There is no reason that a file can't iterate over itself.&nbsp; This has the
185 advantage of keeping the code together.&nbsp; The problem is that you have to
186 discriminate the "regular" section of the file from the iterated section of the
187 file.&nbsp; The library provides the <b>BOOST_PP_IS_ITERATING</b> macro to help
188 in this regard.&nbsp; This macro is defined as <i>1</i> if an iteration is in
189 progress.&nbsp; For example, to merge the contents of "file.h" into the file
190 that iterates it:
191 </div>
192 <div class="code">
193 <pre>
194// sample.h
195#if !BOOST_PP_IS_ITERATING
196
197 #ifndef SAMPLE_H
198 #define SAMPLE_H
199
200 #include &lt;boost/preprocessor/iteration/iterate.hpp&gt;
201
202 template&lt;int&gt; struct sample;
203
204 #define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 5, "sample.h"))
205 ??=include BOOST_PP_ITERATE()
206
207 #endif // SAMPLE_H
208
209#else
210
211 template&lt;&gt; struct sample&lt;BOOST_PP_ITERATION()&gt; { };
212
213#endif
214</pre>
215 </div>
216 <div>
217 Using the same file like this raises another issue.&nbsp; What happens when a
218 file performs two separate file iterations over itself?&nbsp; This is the
219 purpose of the optional flags parameter.&nbsp; It is used to discriminate
220 between separate iterations.
221 </div>
222 <div class="code">
223 <pre>
224// sample.h
225#if !BOOST_PP_IS_ITERATING
226
227 #ifndef SAMPLE_H
228 #define SAMPLE_H
229
230 #include &lt;boost/preprocessor/iteration/iterate.hpp&gt;
231 #include &lt;boost/preprocessor/repetition/enum_params.hpp&gt;
232 #include &lt;boost/preprocessor/repetition/enum_shifted_params.hpp&gt;
233
234 template&lt;int&gt; struct sample;
235
236 #define BOOST_PP_ITERATION_PARAMS_1 (4, (1, 5, "sample.h", 1))
237 ??=include BOOST_PP_ITERATE()
238
239 template&lt;class T, class U&gt; struct typelist_t {
240 typedef T head;
241 typedef U tail;
242 };
243
244 template&lt;int&gt; struct typelist;
245 struct null_t;
246
247 template&lt;&gt; struct typelist&lt;1&gt; {
248 template&lt;class T0&gt; struct args {
249 typedef typelist_t&lt;T0, null_t&gt; type;
250 };
251 };
252
253 #ifndef TYPELIST_MAX
254 #define TYPELIST_MAX 50
255 #endif
256
257 #define BOOST_PP_ITERATION_PARAMS_1 (4, (2, TYPELIST_MAX, "sample.h", 2))
258 ??=include BOOST_PP_ITERATE()
259
260 #endif // SAMPLE_H
261
262#elif BOOST_PP_ITERATION_FLAGS() == 1
263
264 template&lt;&gt; struct sample&lt;BOOST_PP_ITERATION()&gt; { };
265
266#elif BOOST_PP_ITERATION_FLAGS() == 2
267
268 #define N BOOST_PP_ITERATION()
269
270 template&lt;&gt; struct typelist&lt;N&gt; {
271 template&lt;BOOST_PP_ENUM_PARAMS(N, class T)&gt; struct args {
272 typedef typelist_t&lt;
273 T0,
274 typename typelist&lt;N - 1&gt;::args&lt;BOOST_PP_ENUM_SHIFTED_PARAMS(N, T)&gt;::type
275 &gt; type;
276 };
277 };
278
279 #undef N
280
281#endif
282</pre>
283 </div>
284 <div>
285 Notice the use of the "flags" parameter (which is accessed through <b>BOOST_PP_ITERATION_FLAGS</b>()).&nbsp;
286 It discriminates between our recurring <code>sample</code> iteration and a
287 typelist linearization iteration.&nbsp;
288 </div>
289 <div>
290 The second iteration illustrates the power of the file iteration
291 mechanism.&nbsp; It generates typelist linearizations of the form <code>typelist&lt;3&gt;::args&lt;int,
292 double, char&gt;::type</code>.
293 </div>
294 <div>
295 Actually, to continue the typelist example, with the help of another iteration
296 we can <i>fully</i> linearize typelist creation....
297 </div>
298 <div class="code">
299 <pre>
300// extract.h
301#if !BOOST_PP_IS_ITERATING
302
303 #ifndef EXTRACT_H
304 #define EXTRACT_H
305
306 #include &lt;boost/preprocessor/iteration/iterate.hpp&gt;
307 #include &lt;boost/preprocessor/repetition/enum.hpp&gt;
308 #include &lt;boost/preprocessor/repetition/enum_params.hpp&gt;
309 #include &lt;boost/preprocessor/repetition/enum_trailing_params.hpp&gt;
310
311 // certain types such as "void" can't be function argument types
312
313 template&lt;class T&gt; struct incomplete {
314 typedef T type;
315 };
316
317 template&lt;class T&gt; struct strip_incomplete {
318 typedef T type;
319 };
320
321 template&lt;class T&gt; struct strip_incomplete&lt;incomplete&lt;T&gt; &gt; {
322 typedef T type;
323 };
324
325 template&lt;template&lt;int&gt; class output, class func_t&gt; struct extract;
326
327 #ifndef EXTRACT_MAX
328 #define EXTRACT_MAX 50
329 #endif
330
331 #define BOOST_PP_ITERATION_PARAMS_1 (3, (1, EXTRACT_MAX, "extract.h"))
332 ??=include BOOST_PP_ITERATE()
333
334 #endif // EXTRACT_H
335
336#else
337
338 #define N BOOST_PP_ITERATION()
339 #define STRIP(z, n, _) \
340 typename strip_incomplete&lt;T ## n&gt;::type \
341 /**/
342
343 template&lt;template&lt;int&gt; class output, class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)&gt;
344 struct extract&lt;R (BOOST_PP_ENUM_PARAMS(N, T))&gt; {
345 typedef typename output&lt;N&gt;::template args&lt;BOOST_PP_ENUM(N, STRIP, nil)&gt;::type type;
346 };
347
348 #undef STRIP
349 #undef N
350
351#endif
352</pre>
353 </div>
354 <div>
355 Now we can define a helper macro to finish the job:
356 </div>
357 <div class="code">
358 <pre>
359#define TYPELIST(args) extract&lt;typelist, void args&gt;::type
360
361typedef TYPELIST((int, double, incomplete&lt;void&gt;)) xyz;
362</pre>
363 </div>
364 <div>
365 There are two minor caveats with this result.&nbsp; First, certain types like <code>void</code>
366 can't be the type of an argument, so they have to be wrapped with <code>incomplete&lt;T&gt;</code>.&nbsp;
367 Second, the necessary double parenthesis is annoying.&nbsp; If and when C++
368 gets C99's variadic macros, <code>TYPELIST</code> can be redefined:
369 </div>
370 <div class="code">
371 <pre>
372#define TYPELIST(...) extract&lt;typelist, void (__VA_ARGS__)&gt;::type
373
374typedef TYPELIST(int, double, short) xyz;
375</pre>
376 </div>
377 <div>
378 Note also that both the lower and upper bounds of an iteration are also
379 accessible inside an iteration with <b>BOOST_PP_ITERATION_START</b>() and <b>BOOST_PP_ITERATION_FINISH</b>().
380 </div>
381 <div>
382 It is my hope that the explanation and examples presented here demonstrate the
383 power of file iteration.&nbsp; Even so, this is just the beginning.&nbsp; The
384 file iteration mechanism also defines a full suite of facilities to support
385 multidimensional iteration.
386 </div>
387 <h4>
388 Multiple Dimensions
389 </h4>
390 <div>
391 The file iteration mechanism supports up to <b>BOOST_PP_LIMIT_ITERATION_DIM</b>
392 dimensions.&nbsp; The first dimension (i.e. the outermost) we have already used
393 above.&nbsp; In order to use the second dimension (inside the first), we simply
394 have to replace the placeholder <i>x</i> with <i>2</i> instead of <i>1</i>.
395 </div>
396 <div class="code">
397 <pre>
398#define BOOST_PP_ITERATION_PARAMS_2 /* ... */
399 ^
400</pre>
401 </div>
402 <div>
403 ...or...
404 </div>
405 <div class="code">
406 <pre>
407#define BOOST_PP_FILENAME_2 /* ... */
408 ^
409</pre>
410 </div>
411 <div>
412 Each dimension must be used <i>in order</i> starting with <i>1</i>.&nbsp;
413 Therefore, the above can <i>only</i> be valid immediately inside the first
414 dimension.&nbsp;
415 </div>
416 <div>
417 At this point, further explanation is necessary regarding <b>BOOST_PP_ITERATION</b>,
418 <b>BOOST_PP_ITERATION_START</b>, and <b>BOOST_PP_ITERATION_FINISH</b>.&nbsp; <b>BOOST_PP_ITERATION</b>()
419 expands to the iteration value of the <i>current</i> dimension--regardless of
420 what dimension that is.&nbsp; Likewise, <b>BOOST_PP_ITERATION_START</b>() and <b>BOOST_PP_ITERATION_FINISH</b>()
421 expand to the lower and upper bounds of the <i>current</i> dimension.&nbsp;
422 Using the following pseudo-code as reference:
423 </div>
424 <div class="code">
425 <pre>
426for (int i = start(1); i <= finish(1); ++i) {
427 // A
428 for (int j = start(2); j <= finish(2); ++j) {
429 // B
430 }
431 // C
432}
433</pre>
434 </div>
435 <div>
436 At point <i>A</i>, <b>BOOST_PP_ITERATION</b>() refers to <code>i</code>.&nbsp; <b>BOOST_PP_ITERATION_START</b>()
437 and <b>BOOST_PP_ITERATION_FINISH</b>() refer to <code>start(1)</code> and <code>finish(1)</code>
438 respectively.&nbsp; At point <i>B</i>, however, <b>BOOST_PP_ITERATION</b>()
439 refers to <code>j</code>--the <i>current</i> iteration value at point <i>B</i>.&nbsp;
440 The same is true for <b>BOOST_PP_ITERATION_START</b>() which refers to <code>start(2)</code>,
441 etc..
442 </div>
443 <div>
444 If separate files are used for each dimension, then there are no major
445 problems, and using multiple dimensions is straightforward.&nbsp; However, if
446 more than one dimension is located in the same file, they need to be
447 distinguished from one another.&nbsp; The file iteration mechanism provides the
448 macro <b>BOOST_PP_ITERATION_DEPTH</b> for this purpose:
449 </div>
450 <div class="code">
451 <pre>
452// file.h
453#if !BOOST_PP_IS_ITERATING
454
455 #ifndef FILE_H
456 #define FILE_H
457
458 #include &lt;boost/preprocessor/iteration/iterate.hpp&gt;
459
460 #define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 2, "file.h"))
461 ??=include BOOST_PP_ITERATE()
462
463 #endif // FILE_H
464
465#elif BOOST_PP_ITERATION_DEPTH() == 1
466
467 // A
468 + BOOST_PP_ITERATION()
469
470 #define BOOST_PP_ITERATION_PARAMS_2 (3, (1, 2, "file.h"))
471 ??=include BOOST_PP_ITERATE()
472
473 // C
474
475#elif BOOST_PP_ITERATION_DEPTH() == 2
476
477 // B
478 - BOOST_PP_ITERATION()
479
480#endif
481</pre>
482 </div>
483 <div>
484 This will result to the following:
485 </div>
486 <div>
487 <pre>
488+ 1
489- 1
490- 2
491+ 2
492- 1
493- 2
494</pre>
495 </div>
496 <div>
497 Multiple dimensions raise another question.&nbsp; How does one access the state
498 of dimensions <i>other</i> than the current dimension?&nbsp; In other words,
499 how does one access <code>i</code> at point <i>A</i>?&nbsp; Because of the
500 preprocessor's lazy evaluation, this <i>doesn't</i> work....
501 </div>
502 <div class="code">
503 <pre>
504// ...
505
506#elif BOOST_PP_ITERATION_DEPTH() == 1
507
508 #define I BOOST_PP_ITERATION()
509
510 #define BOOST_PP_ITERATION_PARAMS_2 (3, (1, 2, "file.h"))
511 ??=include BOOST_PP_ITERATE()
512
513 #undef I
514
515#elif BOOST_PP_ITERATION_DEPTH() == 2
516
517 #define J BOOST_PP_ITERATION()
518
519 // use I and J
520
521 #undef I
522
523#endif
524</pre>
525 </div>
526 <div>
527 The problem here is that <code>I</code> refers to <b>BOOST_PP_ITERATION</b>(),
528 not to the <i>value</i> of <b>BOOST_PP_ITERATION</b>() at the point of <code>I</code>'s
529 definition.
530 </div>
531 <div>
532 The library provides macros to access these values in two ways--absolutely or
533 relatively.&nbsp; The first variety accesses a value of a specific iteration
534 frame (i.e. dimension).&nbsp; To access the iteration value of the first
535 dimension--from <i>any</i> dimension--<b>BOOST_PP_FRAME_ITERATION</b>(<i>1</i>)
536 is used.&nbsp; To access the iteration value of the second dimension, <b>BOOST_PP_FRAME_ITERATION</b>(<i>2</i>)
537 is used, and so on.&nbsp;
538 </div>
539 <div>
540 There are also frame versions to access the lower bound, the upper bound, and
541 the flags of a dimension:&nbsp; <b>BOOST_PP_FRAME_START</b>, <b>BOOST_PP_FRAME_FINISH</b>,
542 and <b>BOOST_PP_FRAME_FLAGS</b>.
543 </div>
544 <div>
545 So, to fix the last example, we modify the definition of <code>I</code>....
546 </div>
547 <div class="code">
548 <pre>
549// ...
550
551#elif BOOST_PP_ITERATION_DEPTH() == 1
552
553 #define I BOOST_PP_FRAME_ITERATION(1)
554
555// ...
556</pre>
557 </div>
558 <div>
559 The library also provides macros to access values in dimensions <i>relative</i>
560 to the current dimension (e.g. the <i>previous</i> dimension).&nbsp; These
561 macros take an argument that is interpreted as an offset from the current
562 frame.&nbsp; For example, <b>BOOST_PP_RELATIVE_ITERATION</b>(<i>1</i>) always
563 refers to the outer dimension immediately previous to the current
564 dimension.&nbsp; An argument of <i>0</i> is interpreted as an offset of <i>0</i>
565 which causes <b>BOOST_PP_RELATIVE_ITERATION</b>(<i>0</i>) to be equivalent to <b>BOOST_PP_ITERATION</b>().&nbsp;
566 <b>BOOST_PP_RELATIVE_ITERATION</b>(<i>2</i>) refers to the iteration value of
567 the dimension immediately preceding the dimension that precedes the current
568 dimension.&nbsp;
569 </div>
570 <div>
571 The lower and upper bounds of a dimension can be accessed in this fashion as
572 well with <b>BOOST_PP_RELATIVE_START</b> and <b>BOOST_PP_RELATIVE_FINISH</b>.&nbsp;
573 The flags of a relative dimension can be accessed with <b>BOOST_PP_RELATIVE_FLAGS</b>.
574 </div>
575 <h4>
576 Relativity
577 </h4>
578 <div>
579 I mentioned earlier that there is a reason that there are two ways to
580 parametize the mechanism.&nbsp; The reason is dimensional abstraction.&nbsp; In
581 certain situations the dimension is unknown by the code that is being
582 iterated--possibly because the code is reused at multiple, different
583 dimensions.&nbsp; If that code needs to iterate again, it has to define the
584 right parameters (based on the dimension) for the mechanism to consume.&nbsp;
585 </div>
586 <div>
587 All of the macro state maintained by the mechanism can be referred to in an
588 indirect way relative to a dimension.&nbsp; This is the purpose of the <b>BOOST_PP_RELATIVE_</b>
589 accessors.&nbsp;
590 </div>
591 <div>
592 Likewise, the user-defined <i>named external arguments</i> can be defined this
593 way as well--<i>except</i> the name of the file to iterate.&nbsp; Because the
594 lower and upper boundaries are <i>evaluated</i> by the mechanism, the
595 implementation no longer needs the macro <b>BOOST_PP_ITERATION_LIMITS</b>, and
596 the identifier can be reused for each dimension of iteration.&nbsp;
597 </div>
598 <div>
599 Unfortunately, the filename is a different story.&nbsp; The library has no way
600 to evaluate the quoted (or angle-bracketed) text.&nbsp; Therefore, it has to
601 use a different macro for each dimension.&nbsp; That is the purpose of the <b>BOOST_PP_FILENAME_<i>x</i></b>
602 macros.&nbsp; They exist to isolate the only non-abstractable piece of data
603 required by the mechanism.&nbsp;
604 </div>
605 <div>
606 In order to define the filename in an abstract fashion, you need to do
607 something like this:
608 </div>
609 <div class="code">
610 <pre>
611#define UNIQUE_TO_FILE "some_file.h"
612
613#if BOOST_PP_ITERATION_DEPTH() == 0
614 #define BOOST_PP_FILENAME_1 UNIQUE_TO_FILE
615#elif BOOST_PP_ITERATION_DEPTH() == 1
616 #define BOOST_PP_FILENAME_2 UNIQUE_TO_FILE
617#elif BOOST_PP_ITERATION_DEPTH() == 2
618 #define BOOST_PP_FILENAME_3 UNIQUE_TO_FILE
619
620// ... up to BOOST_PP_LIMIT_ITERATION_DIM
621
622#endif
623</pre>
624 </div>
625 <div>
626 The intent is to avoid having to do this for anything but the filename.&nbsp;
627 If this needs to be done more than once in a file (<b>BOOST_PP_FILENAME_<i>x</i></b>
628 is undefined by the mechanism after it is used.), consider using a separate
629 file to make the proper definition:
630 </div>
631 <div class="code">
632 <pre>
633# // detail/define_file_h.h
634# ifndef FILE_H
635# error FILE_H is not defined
636# endif
637#
638# if BOOST_PP_ITERATION_DEPTH() == 0
639# define BOOST_PP_FILENAME_1 FILE_H
640# elif BOOST_PP_ITERATION_DEPTH() == 1
641# define BOOST_PP_FILENAME_2 FILE_H
642# elif BOOST_PP_ITERATION_DEPTH() == 2
643# define BOOST_PP_FILENAME_3 FILE_H
644# elif BOOST_PP_ITERATION_DEPTH() == 3
645# define BOOST_PP_FILENAME_4 FILE_H
646# elif BOOST_PP_ITERATION_DEPTH() == 4
647# define BOOST_PP_FILENAME_5 FILE_H
648# else
649# error unsupported iteration dimension
650# endif
651</pre>
652 </div>
653 <div>
654 And then use it like this....
655 </div>
656 <div class="code">
657 <pre>
658// file.h
659#if !BOOST_PP_IS_ITERATING
660
661 #ifndef FILE_H
662 #define FILE_H "file.h"
663
664 #define BOOST_PP_ITERATION_LIMITS (1, 10)
665 #include "detail/define_file_h.h"
666
667 ??=include BOOST_PP_ITERATE()
668
669#endif // FILE_H
670
671#else
672 // iterated portion
673#endif
674</pre>
675 </div>
676 <div>
677 With a little effort like this, it is possible to maintain the abstraction
678 without the code bloat that would otherwise be required.&nbsp; Unfortunately,
679 this is not a completely general solution as it would need to be done for each
680 unique filename, but it is better than nothing.
681 </div>
682 <h4>
683 Conclusion
684 </h4>
685 <div>
686 That about covers the facilities that are available from the mechanism.&nbsp;
687 Using these facilities, let's implement a <code>function_traits</code> template
688 to demonstrate a full-fledge use of the mechanism.
689 </div>
690 <h4>
691 Function Traits - An Involved Example
692 </h4>
693 <div>
694 Implementing a comprehensive <code>function_traits</code> template metafunction
695 requires the use of every major part of the file iteration mechanism.&nbsp;
696 </div>
697 <div>
698 (This example makes no attempt of work around compiler deficiencies and exists
699 only to illustrate the mechanism.)
700 </div>
701 <div>
702 The result should have the following features:
703 </div>
704 <ul>
705 <li>
706 return type</li>
707 <li>
708 number and types of parameters</li>
709 <li>
710 whether or not the type is a pointer-to-function, reference-to-function,
711 pointer-to-member-function, or a plain function type</li>
712 <li>
713 whether the type has an ellipsis</li>
714 <li>
715 if not a pointer-to-member-function, the equivalent pointer-to-function,
716 reference-to-function, and function type</li>
717 <li>
718 otherwise, the pointer-to-member type, the class type to which it refers, and
719 whether it is const and/or volatile qualified</li>
720 </ul>
721 <div>
722 There are a myriad of ways that this can be implemented.&nbsp; I'll give a
723 brief summary here of what is happening in the implementation below.&nbsp;
724 </div>
725 <div>
726 The implementation inherently has to deal with function arity.&nbsp; Therefore,
727 at minimum, we need to iterate over function arities and define partial
728 specializations of the primary template <code>function_traits</code>.&nbsp; The
729 situation is further complicated by variadic functions (i.e. functions with an
730 ellipsis).&nbsp; Therefore, for every arity, we need a variadic version as
731 well.
732 </div>
733 <div>
734 We also need to handle pointers-to-member-functions.&nbsp; This implies that we
735 have to handle not just arity and variadics, but also cv-qualifications.&nbsp;
736 </div>
737 <div>
738 For the sake of clarity, the implementation below handles function types and
739 pointers-to-member-functions separately.&nbsp; They could be merged, but the
740 result would be significantly messier.
741 </div>
742 <div>
743 To handle function types, the implementation below iterates over function
744 arities.&nbsp; For each arity, it iterates over each parameter to provide
745 access to each individually.&nbsp; It then re-includes itself to define a
746 variadic specialization of the same arity.&nbsp; It performs the rough
747 equivalent of the following pseudo-code:
748 </div>
749 <div class="code">
750 <pre>
751void make_spec(int i, bool variadic) {
752 :open function_traits&lt;i, variadic&gt;
753 for (int j = 0; j < i; ++j) {
754 :parameter&lt;j&gt;
755 }
756 :close
757 if (!variadic) {
758 make_spec(i, true);
759 }
760 return;
761}
762
763void function_types(int max_arity) {
764 for (int i = 0; i <= max_arity; ++i) {
765 make_spec(i, false);
766 }
767 return;
768}
769</pre>
770 </div>
771 <div>
772 The implementation of pointers-to-member-functions is a bit different.&nbsp;
773 First, it iterates over cv-qualifiers.&nbsp; For each cv-qualifier, it iterates
774 over function arities.&nbsp; For each function arity, it iterates again over
775 each parameter.&nbsp; It then re-includes itself to define a variadic
776 specialization of the same arity....
777 </div>
778 <div class="code">
779 <pre>
780void make_spec(int j, const char* cv, bool variadic) {
781 :open function_traits&lt;j, cv, variadic&gt;
782 for (int k = 0; k < j; ++k) {
783 parameter&lt;k&gt;
784 }
785 :close
786 if (!variadic) {
787 make_spec(j, cv, true);
788 }
789 return;
790}
791
792void gen_arities(const char* cv, int max_arity) {
793 for (int j = 0; j <= max_arity; ++j) {
794 make_spec(j, cv, false);
795 }
796 return;
797}
798
799void pointers_to_members(int max_arity) {
800 static const char* cv_qualifiers[] = { "", "const", "volatile", "const volatile" };
801 for (int i = 0; i < 4; ++i) {
802 gen_arities(cv_qualifiers[i], max_arity);
803 }
804 return;
805}
806</pre>
807 </div>
808 <div>
809 Here is the complete implementation.&nbsp; This example represents the power of
810 the file iteration mechanism as well as the library in general, so follow it
811 carefully if you wish to fully understand what the mechanism does....
812 </div>
813 <div class="code">
814 <pre>
815// function_traits.hpp
816
817#if !BOOST_PP_IS_ITERATING
818
819#ifndef FUNCTION_TRAITS_HPP
820#define FUNCTION_TRAITS_HPP
821
822#include &lt;boost/preprocessor/cat.hpp&gt;
823#include &lt;boost/preprocessor/facilities/apply.hpp&gt;
824#include &lt;boost/preprocessor/iteration/iterate.hpp&gt;
825#include &lt;boost/preprocessor/iteration/self.hpp&gt;
826#include &lt;boost/preprocessor/repetition/enum_params.hpp&gt;
827#include &lt;boost/preprocessor/repetition/enum_trailing_params.hpp&gt;
828#include &lt;boost/preprocessor/tuple/elem.hpp&gt;
829
830// enable user-expansion
831#ifndef FUNCTION_TRAITS_MAX_ARITY
832 #define FUNCTION_TRAITS_MAX_ARITY 15
833#endif
834
835namespace detail {
836
837// avoid replication of "default" values
838struct function_traits_base {
839 static const bool is_plain = false;
840 static const bool is_pointer = false;
841 static const bool is_reference = false;
842 static const bool is_member = false;
843};
844
845} // detail
846
847// no definition
848template&lt;class&gt; struct function_traits;
849
850// extract ellipsis state
851#define ELLIPSIS(n) \
852 BOOST_PP_APPLY( \
853 BOOST_PP_TUPLE_ELEM(2, n, ELLIPSIS_I) \
854 ) \
855 /**/
856
857// iterate over function arities for function types
858#define BOOST_PP_ITERATION_PARAMS_1 \
859 (4, (0, FUNCTION_TRAITS_MAX_ARITY, "function_traits.hpp", 0)) \
860 /**/
861??=include BOOST_PP_ITERATE()
862
863// obtain a cv-qualifier by index
864#define QUALIFIER(n) \
865 BOOST_PP_APPLY( \
866 BOOST_PP_TUPLE_ELEM( \
867 4, n, \
868 (BOOST_PP_NIL, (const), (volatile), (const volatile)) \
869 ) \
870 ) \
871 /**/
872
873// iterate over cv-qualifiers for pointers-to-members
874#define BOOST_PP_ITERATION_PARAMS_1 \
875 (4, (0, 3, "function_traits.hpp", 1)) \
876 /**/
877??=include BOOST_PP_ITERATE()
878
879// remove temporary macros
880#undef QUALIFIER
881#undef ELLIPSIS
882
883// overriding jumper for pointers-to-functions
884template&lt;class T&gt; struct function_traits&lt;T*&gt; : function_traits&lt;T&gt; {
885 static const bool is_plain = false;
886 static const bool is_pointer = true;
887};
888
889// overriding jumper for references-to-functions
890template&lt;class T&gt; struct function_traits&lt;T&amp;&gt; : function_traits&lt;T&gt; {
891 static const bool is_plain = false;
892 static const bool is_reference = true;
893};
894
895// eof
896#endif // FUNCTION_TRAITS_HPP
897
898// specializations for function types
899#elif BOOST_PP_ITERATION_DEPTH() == 1 \
900 &amp;&amp; BOOST_PP_ITERATION_FLAGS() == 0 \
901 /**/
902
903 // define ellipsis state
904 #if BOOST_PP_IS_SELFISH
905 #define ELLIPSIS_I ((true), (...))
906 #else
907 #define ELLIPSIS_I ((false), BOOST_PP_NIL)
908 #endif
909
910 #define N BOOST_PP_ITERATION()
911
912 template&lt;class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)&gt;
913 struct function_traits&lt;R (BOOST_PP_ENUM_PARAMS(N, T) ELLIPSIS(1))&gt;
914 : detail::function_traits_base {
915 static const bool is_plain = true;
916 typedef R function_type(BOOST_PP_ENUM_PARAMS(N, T) ELLIPSIS(1));
917 typedef function_type* pointer_type;
918 typedef function_type&amp; reference_type;
919 static const bool has_ellipsis = ELLIPSIS(0);
920 typedef R return_type;
921 static const int parameter_count = N;
922 template&lt;int, class D = int&gt; struct parameter;
923 #if N
924 // iterate over parameters
925 #define BOOST_PP_ITERATION_PARAMS_2 \
926 (3, (0, N - 1, "function_traits.hpp")) \
927 /**/
928 ??=include BOOST_PP_ITERATE()
929 #endif
930 };
931
932 #undef N
933 #undef ELLIPSIS_I
934
935 // re-include this section for an ellipsis variant
936 #if !BOOST_PP_IS_SELFISH
937 #define BOOST_PP_INDIRECT_SELF "function_traits.hpp"
938 ??=include BOOST_PP_INCLUDE_SELF()
939 #endif
940
941// iteration over cv-qualifiers
942#elif BOOST_PP_ITERATION_DEPTH() == 1 \
943 &amp;&amp; BOOST_PP_ITERATION_FLAGS() == 1 \
944 /**/
945
946 #define BOOST_PP_ITERATION_PARAMS_2 \
947 (3, (0, FUNCTION_TRAITS_MAX_ARITY, "function_traits.hpp")) \
948 /**/
949 ??=include BOOST_PP_ITERATE()
950
951// generate specializations for pointers-to-members
952#elif BOOST_PP_ITERATION_DEPTH() == 2 \
953 &amp;&amp; BOOST_PP_FRAME_FLAGS(1) == 1 \
954
955 // define ellipsis state
956 #if BOOST_PP_IS_SELFISH
957 #define ELLIPSIS_I ((true), (...))
958 #else
959 #define ELLIPSIS_I ((false), BOOST_PP_NIL)
960 #endif
961
962 #define N BOOST_PP_ITERATION()
963 #define Q QUALIFIER(BOOST_PP_FRAME_ITERATION(1))
964
965 template&lt;class R, class O BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)&gt;
966 struct function_traits&lt;R (O::*)(BOOST_PP_ENUM_PARAMS(N, T) ELLIPSIS(1)) Q&gt;
967 : detail::function_traits_base {
968 static const bool is_member = true;
969 typedef R (O::* pointer_to_member_type)(BOOST_PP_ENUM_PARAMS(N, T) ELLIPSIS(1)) Q;
970 typedef O class_type;
971 typedef Q O qualified_class_type;
972 static const bool has_ellipsis = ELLIPSIS(0);
973 static const bool is_const =
974 BOOST_PP_FRAME_ITERATION(1) == 1 || BOOST_PP_FRAME_ITERATION(1) == 3;
975 static const bool is_volatile =
976 BOOST_PP_FRAME_ITERATION(1) == 2 || BOOST_PP_FRAME_ITERATION(1) == 3;
977 typedef R return_type;
978 static const int parameter_count = N;
979 template&lt;int, class D = int&gt; struct parameter;
980 #if N
981 // iterate over parameters
982 #define BOOST_PP_ITERATION_PARAMS_3 \
983 (3, (0, N - 1, "function_traits.hpp")) \
984 /**/
985 ??=include BOOST_PP_ITERATE()
986 #endif
987 };
988
989 #undef Q
990 #undef N
991 #undef ELLIPSIS_I
992
993 // re-include this section for an ellipsis variant
994 #if !BOOST_PP_IS_SELFISH
995 #define BOOST_PP_INDIRECT_SELF "function_traits.hpp"
996 ??=include BOOST_PP_INCLUDE_SELF()
997 #endif
998
999// parameter specializations
1000#else
1001
1002 #define X BOOST_PP_ITERATION()
1003
1004 template&lt;class D&gt; struct parameter&lt;X, D&gt; {
1005 typedef BOOST_PP_CAT(T, X) type;
1006 };
1007
1008 #undef X
1009
1010#endif
1011</pre>
1012 </div>
1013 <div>
1014 One problem that still exists is the lack of support for <code>throw</code> specifications.&nbsp;
1015 There is no way that we can completely handle it anyway because we cannot
1016 partially specialize on <code>throw</code> specifications.&nbsp; However, we
1017 could accurately report the "actual" function type, etc., including the <code>throw</code>
1018 specification (which the above implementation doesn't do, as it reconstructs
1019 those types).&nbsp; If you like, you can figure out how to do that on your own
1020 as an exercise.&nbsp;
1021 </div>
1022 <h4>
1023 See Also
1024 </h4>
1025 <ul>
1026 <li>
1027 <a href="../ref/iterate.html">BOOST_PP_ITERATE</a></li>
1028 </ul>
1029 <div class="sig">
1030 - Paul Mensonides
1031 </div>
1032 <hr size="1">
1033 <div style="margin-left: 0px;">
1034