]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | <html> |
2 | <head> | |
3 | <title>evaluated_slots.html</title> | |
4 | <link rel="stylesheet" type="text/css" href="../styles.css"> | |
5 | </head> | |
6 | <body> | |
7 | <h4>Evaluated Slots</h4> | |
8 | <div> | |
9 | The evaluated slot mechanism is a tool to fully evaluate a constant integral expression and avoid the lazy evaluation normally performed by the preprocessor. | |
10 | </div> | |
11 | <h4>Tutorial</h4> | |
12 | <div> | |
13 | In order to understand the use of such a mechanism, I will start with a simple file-iteration example. | |
14 | Consider the following scenario.... | |
15 | </div> | |
16 | <div class ="code"><pre> | |
17 | for (int i = 0; i < 10; ++i) { | |
18 | for (int j = 0; j < i; ++j) { | |
19 | // ... use i and j | |
20 | } | |
21 | } | |
22 | </pre></div> | |
23 | <div> | |
24 | The above is a simple runtime model of the following multidimensional file-iteration.... | |
25 | </div> | |
26 | <div class="code"><pre> | |
27 | // file.hpp | |
28 | #if !BOOST_PP_IS_ITERATING | |
29 | #ifndef FILE_HPP_ | |
30 | #define FILE_HPP_ | |
31 | ||
32 | #include <boost/preprocessor/iteration/iterate.hpp> | |
33 | ||
34 | #define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 9, "file.hpp")) | |
35 | #include BOOST_PP_ITERATE() | |
36 | ||
37 | #endif // FILE_HPP_ | |
38 | #elif BOOST_PP_ITERATION_DEPTH() == 1 | |
39 | #define I BOOST_PP_ITERATION() | |
40 | ||
41 | #define BOOST_PP_ITERATION_PARAMS_2 (3, (0, I, "file.hpp")) | |
42 | #include BOOST_PP_ITERATE() | |
43 | ||
44 | #undef I | |
45 | #elif BOOST_PP_ITERATION_DEPTH() == 2 | |
46 | #define J BOOST_PP_ITERATION() | |
47 | ||
48 | // use I and J | |
49 | ||
50 | #undef J | |
51 | #endif | |
52 | </pre></div> | |
53 | <div> | |
54 | There is a problem with the code above. | |
55 | The writer expected <i>I</i> to refer the previous iteration frame. | |
56 | However, that is not the case. | |
57 | When the user refers to <i>I</i>, he is actually referring to <b>BOOST_PP_ITERATION</b>(), | |
58 | not the value of <b>BOOST_PP_ITERATION</b>() at the point of definition. | |
59 | Instead, it refers to exactly the same value to which <i>J</i> refers. | |
60 | </div> | |
61 | <div> | |
62 | The problem is that the preprocessor always evaluates everything with lazy evaluation. | |
63 | To solve the problem, we need <i>I</i> to be <i>evaluated</i> here: | |
64 | </div> | |
65 | <div class="code"><pre> | |
66 | // ... | |
67 | #elif BOOST_PP_ITERATION_DEPTH() == 1 | |
68 | #define I BOOST_PP_ITERATION() | |
69 | // ... | |
70 | </pre></div> | |
71 | <div> | |
72 | Fortunately, the library offers a mechanism to do just that: evaluated slots. | |
73 | The following code uses this mechanism to "fix" the example above... | |
74 | </div> | |
75 | <div class="code"><pre> | |
76 | // ... | |
77 | #elif BOOST_PP_ITERATION_DEPTH() == 1 | |
78 | #define BOOST_PP_VALUE BOOST_PP_ITERATION() | |
79 | #include BOOST_PP_ASSIGN_SLOT(1) | |
80 | #define I BOOST_PP_SLOT(1) | |
81 | // ... | |
82 | </pre></div> | |
83 | <div> | |
84 | There are two steps to the assignment of an evaluated slot. | |
85 | First, the user must define the <i>named external argument</i> <b>BOOST_PP_VALUE</b>. | |
86 | This value must be an integral constant expression. | |
87 | 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>). | |
88 | This will evaluate <b>BOOST_PP_VALUE</b> and assign the result to the slot at index <i>x</i>. | |
89 | </div> | |
90 | <div> | |
91 | To retrieve a slot's value, the user must use <b>BOOST_PP_SLOT</b>(<i>x</i>). | |
92 | </div> | |
93 | <div> | |
94 | In the case above, <i>I</i> is <i>still</i> lazily evaluated. | |
95 | However, it now evaluates to <b>BOOST_PP_SLOT</b>(<i>1</i>). | |
96 | This value <i>will not change</i> unless there is a subsequent call to <b>BOOST_PP_ASSIGN_SLOT</b>(<i>1</i>). | |
97 | </div> | |
98 | <h4>Advanced Techniques</h4> | |
99 | <div> | |
100 | The slot mechanism can also be used to perform calculations: | |
101 | </div> | |
102 | <div class="code"><pre> | |
103 | #include <iostream> | |
104 | ||
105 | #include <boost/preprocessor/slot/slot.hpp> | |
106 | #include <boost/preprocessor/stringize.hpp> | |
107 | ||
108 | #define X() 4 | |
109 | ||
110 | #define BOOST_PP_VALUE 1 + 2 + 3 + X() | |
111 | #include BOOST_PP_ASSIGN_SLOT(1) | |
112 | ||
113 | #undef X | |
114 | ||
115 | int main(void) { | |
116 | std::cout | |
117 | << BOOST_PP_STRINGIZE(BOOST_PP_SLOT(1)) | |
118 | << &std::endl; | |
119 | return 0; | |
120 | } | |
121 | </pre></div> | |
122 | <div> | |
123 | In essence, anything that can be evaluated in an #if (or #elif) preprocessor directive is available <i>except</i> the <i>defined</i> operator. | |
124 | </div> | |
125 | <div> | |
126 | It is even possible to use a particular slot itself while reassigning it: | |
127 | </div> | |
128 | <div class="code"><pre> | |
129 | #define BOOST_PP_VALUE 20 | |
130 | #include BOOST_PP_ASSIGN_SLOT(1) | |
131 | ||
132 | #define BOOST_PP_VALUE 2 * BOOST_PP_SLOT(1) | |
133 | #include BOOST_PP_ASSIGN_SLOT(1) | |
134 | ||
135 | BOOST_PP_SLOT(1) // 40 | |
136 | </pre></div> | |
137 | <h4>See Also</h4> | |
138 | <ul> | |
139 | <li><a href="../ref/assign_slot.html">BOOST_PP_ASSIGN_SLOT</a></li> | |
140 | <li><a href="../ref/limit_slot_count.html">BOOST_PP_LIMIT_SLOT_COUNT</a></li> | |
141 | <li><a href="../ref/slot.html">BOOST_PP_SLOT</a></li> | |
142 | <li><a href="../ref/value.html">BOOST_PP_VALUE</a></li> | |
143 | </ul> | |
144 | <div class="sig">- Paul Mensonides</div> | |
145 | <hr size="1"> | |
146 | <div style="margin-left: 0px;"> | |
147 |