File: evaluated_slots.html

package info (click to toggle)
boost 1.33.1-10
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 100,948 kB
  • ctags: 145,103
  • sloc: cpp: 573,492; xml: 49,055; python: 15,626; ansic: 13,588; sh: 2,099; yacc: 858; makefile: 660; perl: 427; lex: 111; csh: 6
file content (146 lines) | stat: -rw-r--r-- 4,573 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
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>