• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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		<i>� Copyright <a href="http://www.housemarque.com" target="_top">Housemarque Oy</a> 2002</i>
1035		</br><i>� Copyright Paul Mensonides 2002</i>
1036	</div>
1037	<div style="margin-left: 0px;">
1038		<p><small>Distributed under the Boost Software License, Version 1.0. (See
1039		accompanying file <a href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
1040		copy at <a href=
1041		"http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</small></p>
1042	</div>
1043	</body>
1044</html>
1045