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.
Consider the following scenario....
</div>
<divclass ="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....
#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.
The writer expected <i>I</i> to refer the previous iteration frame.
However, that is not the case.
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.
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.
To solve the problem, we need <i>I</i> to be <i>evaluated</i> here:
</div>
<divclass="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: evaluated slots.
The following code uses this mechanism to "fix" the example above...
</div>
<divclass="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.
First, the user must define the <i>named external argument</i><b>BOOST_PP_VALUE</b>.
This value must be an integral constant expression.
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>).
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.
However, it now evaluates to <b>BOOST_PP_SLOT</b>(<i>1</i>).
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>
<divclass="code"><pre>
#include <iostream>
#include <boost/preprocessor/slot/slot.hpp>
#include <boost/preprocessor/stringize.hpp>
#define X() 4
#define BOOST_PP_VALUE 1 + 2 + 3 + X()
#include BOOST_PP_ASSIGN_SLOT(1)
#undef X
int main(void) {
std::cout
<< BOOST_PP_STRINGIZE(BOOST_PP_SLOT(1))
<<&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: