Evaluated Slots

Evaluated slots is a mechanism to fully evaluate a constant expression to avoid the normal lazy evaluation of the preprocessor.

Tutorial

In order to understand the use of such a mechanism, we will start with a simple file iteration example.  Consider the following scenario....
for (int i = 0; i < 10; ++i) {
   for (int j = 0; j < i; ++j) {
      // ... use i and j
   }
}
This is a simple model of the following multiple-depth file iteration....
#if !defined(BOOST_PP_IS_ITERATING)
   #ifndef FILE_HPP
   #define FILE_HPP
   
      #include <boost/preprocessor/iterate.hpp>

      #define BOOST_PP_ITERATION_PARAMS_1 (0, 9, "file.hpp")
      ??=include BOOST_PP_ITERATE()

   #endif
#elif BOOST_PP_ITERATION_DEPTH() == 1
   #define I BOOST_PP_ITERATION()

   #define BOOST_PP_ITERATION_PARAMS_2 (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
There is a big problem with the code above.  The user expected I to refer to the previous iteration frame.  However, that is not the case.  When the user refers to I, he actually is referring to BOOST_PP_ITERATION().  This is exactly the same value to which J refers.
The problem is that the preprocessor always evaluates everything with lazy evaluation.  To solve the problem, we need I to be evaluated here:
// ...
#elif BOOST_PP_ITERATION_DEPTH() == 1
   #define I BOOST_PP_ITERATION()
// ...
The library offers a mechanism to do just that:  evaluated slots.  The following example uses this mechanism to "fix" the example above....
// ...
#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)
// ...
There are two steps to the assignment of an evaluated slot.  First, the user must define the macro BOOST_PP_VALUE.  This value must be an integral constant expression.  Second, the user must include BOOST_PP_ASSIGN_SLOT(x), where x is a value between 1 and BOOST_PP_SLOT_LIMIT.  This will evaluate BOOST_PP_VALUE and assign the result to the slot at index x.
To retrieve a slot's value, the user must use BOOST_PP_SLOT(x).
In the case above, I is still lazily evaluated.  However, it now evaluates to BOOST_PP_SLOT(1).  This value will not change unless there is a subsequent call to BOOST_PP_ASSIGN_SLOT(1).

Advanced...

The slot mechanism can also be used to perform calculations:
#include <iostream>

#include <boost/preprocessor/stringize.hpp>

#define X() 4

#define BOOST_PP_VALUE 1 + 2 + 3 + X()
??=include BOOST_PP_ASSIGN_SLOT(1)

int main(void) {
   std::cout
      << BOOST_PP_STRINGIZE(BOOST_PP_SLOT(1))
      << &std::endl;
   return 0;
}
In essence, anything that can be evaluated in an #if (or #elif) preprocessor directive is available.
Some implementations will allow you to use the defined unary operator in this context and others will not, so don't use defined if you want the code to be fully portable.  For example:
#define X

#define BOOST_PP_VALUE defined(X)
??=include BOOST_PP_ASSIGN_SLOT(1)

BOOST_PP_SLOT(1)

See Also