From 91eba2f11bfc3e50502996b82a5c43132e65e04e Mon Sep 17 00:00:00 2001 From: Paul Mensonides Date: Thu, 7 Nov 2002 23:41:54 +0000 Subject: [PATCH] set -> seq [SVN r16151] --- doc/topics/file_iteration.html | 4 +- doc/topics/reentrancy.html | 369 ++++++++++++++++++--------------- 2 files changed, 205 insertions(+), 168 deletions(-) diff --git a/doc/topics/file_iteration.html b/doc/topics/file_iteration.html index 437ce49..45cbf56 100644 --- a/doc/topics/file_iteration.html +++ b/doc/topics/file_iteration.html @@ -558,10 +558,10 @@ for (int i = start(1); i <= finish(1); ++i) {
The library also provides macros to access values in dimensions relative to the current dimension (e.g. the previous dimension).  These - macros take an argument that is interpreted as an offseq from the current + macros take an argument that is interpreted as an offset from the current frame.  For example, BOOST_PP_RELATIVE_ITERATION(1) always refers to the outer dimension immediately previous to the current - dimension.  An argument of 0 is interpreted as an offseq of 0 + dimension.  An argument of 0 is interpreted as an offset of 0 which causes BOOST_PP_RELATIVE_ITERATION(0) to be equivalent to BOOST_PP_ITERATION().  BOOST_PP_RELATIVE_ITERATION(2) refers to the iteration value of the dimension immediately preceding the dimension that precedes the current diff --git a/doc/topics/reentrancy.html b/doc/topics/reentrancy.html index 1bdc0fa..a39be3a 100644 --- a/doc/topics/reentrancy.html +++ b/doc/topics/reentrancy.html @@ -1,43 +1,51 @@ - - reentrancy.html - - - -

Reentrancy

-
- Macro expansion in the preprocessor is entirely functional.  - Therefore, there is no iteration.  - Unfortunately, the preprocessor also disallows recursion.  - This means that the library must fake iteration or recursion by - defining sets of macros that are implemented similarly.  -
-
- To illustrate, here is a simple concatenation macro: -
-
+	
+		reentrancy.html
+		
+	
+	
+		

+ Reentrancy +

+
+ Macro expansion in the preprocessor is entirely functional.  Therefore, + there is no iteration.  Unfortunately, the preprocessor also disallows + recursion.  This means that the library must fake iteration or recursion + by defining seqs of macros that are implemented similarly.  +
+
+ To illustrate, here is a simple concatenation macro: +
+
+
 #define CONCAT(a, b) CONCAT_D(a, b)
 #define CONCAT_D(a, b) a ## b
 
 CONCAT(a, CONCAT(b, c)) // abc
-
-
- This is fine for a simple case like the above, but what happens in a scenario like the following: -
-
+
+
+
+ This is fine for a simple case like the above, but what happens in a scenario + like the following: +
+
+
 #define AB(x, y) CONCAT(x, y)
 
 CONCAT(A, B(p, q)) // CONCAT(p, q)
-
-
- Because there is no recursion, the example above expands to CONCAT(p, q) rather than pq. -
-
- There are only two ways to "fix" the above.  - First, it can be documented that AB uses CONCAT and disallow usage similar to the above.  - Second, multiple concatenation macros can be provided.... -
-
+
+
+
+ Because there is no recursion, the example above expands to CONCAT(p, q) + rather than pq. +
+
+ There are only two ways to "fix" the above.  First, it can be documented + that AB uses CONCAT and disallow usage similar to the + above.  Second, multiple concatenation macros can be provided.... +
+
+
 #define CONCAT_1(a, b) CONCAT_1_D(a, b)
 #define CONCAT_1_D(a, b) a ## b
 
@@ -47,68 +55,80 @@ CONCAT(A, B(p, q)) // CONCAT(p, q)
 #define AB(x, y) CONCAT_2(x, y)
 
 CONCAT_1(A, B(p, q)) // pq
-
-
- This solves the problem.  - However, it is now necessary to know that AB uses, not only a concatenation macro, - but CONCAT_2 specifically. -
-
- A better solution is to abstract which concatenation macro is used.... -
-
+
+
+
+ This solves the problem.  However, it is now necessary to know that AB + uses, not only a concatenation macro, but CONCAT_2 specifically. +
+
+ A better solution is to abstract which concatenation macro is used.... +
+
+
 #define AB(c, x, y) CONCAT_ ## c(x, y)
 
 CONCAT_1(A, B(2, p, q)) // pq
-
-
- This is an example of generic reentrance, in this case, into a fictional set of concatenation macros.  - The c parameter represents the "state" of the concatenation construct, - and as long as the user keeps track of this state, AB can be used inside of a concatenation macro. -
-
- The library has the same choices.  - It either has to disallow a construct being inside itself or provide multiple, equivalent definitions of a construct - and provide a uniform way to reenter that construct.  - There are several contructs that require recursion (such as BOOST_PP_WHILE).  - Consequently, the library chooses to provide several sets of macros with mechanisms to reenter the set at a macro - that has not already been used. -
-
- In particular, the library must provide reentrance for BOOST_PP_FOR, BOOST_PP_REPEAT, and BOOST_PP_WHILE.  - There are two mechanisms that are used to accomplish this:  state parameters (like the above concatenation example) and automatic recursion. -
-

State Parameters

-
- Each of the above constructs (BOOST_PP_FOR, BOOST_PP_REPEAT, and BOOST_PP_WHILE) has an associated state.  - This state provides the means to reenter the respective construct. -
-
- Several user-defined macros are passed to each of these constructs (for use as predicates, operations, etc.).  - Every time a user-defined macro is invoked, it is passed the current state of the construct that invoked it so that the macro can reenter - the respective set if necessary. -
-
- These states are used in one of two ways--either by concatenating to or passing to another macro. -
-
- There are three types of macros that use these state parameters.  - First, the set itself which is reentered through concatenation.  - Second, corresponding sets that act like they are a part of the the primary set.  - These are also reentered through concatenation.  - And third, macros that internally use the first or second type of macro.  - These macros take the state as an additional argument. -
-
- The state of BOOST_PP_WHILE is symbolized by the letter D.  - Two user-defined macros are passed to BOOST_PP_WHILE--a predicate and an operation.  - When BOOST_PP_WHILE expands these macros, it passes along its state so that these macros - can reenter the BOOST_PP_WHILE set.  -
-
- Consider the following multiplication implementation that illustrates this technique: -
-
+
+
+
+ This is an example of generic reentrance, in this case, into a fictional + seq of concatenation macros.  The c parameter represents the + "state" of the concatenation construct, and as long as the user keeps track of + this state, AB can be used inside of a concatenation macro. +
+
+ The library has the same choices.  It either has to disallow a construct + being inside itself or provide multiple, equivalent definitions of a construct + and provide a uniform way to reenter that construct.  There are + several contructs that require recursion (such as BOOST_PP_WHILE).  + Consequently, the library chooses to provide several seqs of macros with + mechanisms to reenter the seq at a macro that has not already been used. +
+
+ In particular, the library must provide reentrance for BOOST_PP_FOR, BOOST_PP_REPEAT, + and BOOST_PP_WHILE.  There are two mechanisms that are used to + accomplish this:  state parameters (like the above concatenation example) + and automatic recursion. +
+

+ State Parameters +

+
+ Each of the above constructs (BOOST_PP_FOR, BOOST_PP_REPEAT, and BOOST_PP_WHILE) + has an associated state.  This state provides the means to reenter the + respective construct. +
+
+ Several user-defined macros are passed to each of these constructs (for use as + predicates, operations, etc.).  Every time a user-defined macro is + invoked, it is passed the current state of the construct that invoked it so + that the macro can reenter the respective seq if necessary. +
+
+ These states are used in one of two ways--either by concatenating to or passing + to another macro. +
+
+ There are three types of macros that use these state parameters.  First, + the seq itself which is reentered through concatenation.  Second, + corresponding seqs that act like they are a part of the the primary seq.  + These are also reentered through concatenation.  And third, macros that + internally use the first or second type of macro.  These macros take the + state as an additional argument. +
+
+ The state of BOOST_PP_WHILE is symbolized by the letter D.  + Two user-defined macros are passed to BOOST_PP_WHILE--a predicate and an + operation.  When BOOST_PP_WHILE expands these macros, it passes + along its state so that these macros can reenter the BOOST_PP_WHILE seq.  +
+
+ Consider the following multiplication implementation that illustrates this + technique: +
+
+
 // The addition interface macro.
 // The _D signifies that it reenters
 // BOOST_PP_WHILE with concatenation.
@@ -175,79 +195,96 @@ CONCAT_1(A, B(2, p, q)) // pq
    /**/
 
 MUL(3, 2) // expands to 6
-
-
- There are a couple things to note in the above implementation.  - First, note how ADD_D reenters BOOST_PP_WHILE using the d state parameter.  - Second, note how MUL's operation, which is expanded by BOOST_PP_WHILE, passes the state - on to ADD_D.  - This illustrates state reentrance by both argument and concatenation. -
-
- For every macro in the library that uses BOOST_PP_WHILE, - there is a state reentrant variant.  - If that variant uses an argument rather than concatenation, it is suffixed by _D to symbolize its - method of reentrance.  - Examples or this include the library's own BOOST_PP_ADD_D and BOOST_PP_MUL_D.  - If the variant uses concatenation, it is suffixed by an underscore.  - It is completed by concatenation of the state.  - This includes BOOST_PP_WHILE itself with BOOST_PP_WHILE_ ## d and, for example, - BOOST_PP_LIST_FOLD_LEFT with BOOST_PP_LIST_FOLD_LEFT_ ## d. -
-
- The same set of conventions are used for BOOST_PP_FOR and BOOST_PP_REPEAT, but with the letters - R and Z, respectively, to symbolize their states. -
-
- Also note that the above MUL implementation, though not immediately obvious, is using all three - types of reentrance.  - Not only is it using both types of state reentrance, it is also using automatic recursion.... -
-

Automatic Recursion

-
- Automatic recursion is a technique that vastly simplifies the use of reentrant constructs.  - It is used by simply not using any state parameters at all. -
-
- The MUL example above uses automatic recursion when it uses BOOST_PP_WHILE by itself.  - In other words, MUL can still be used inside BOOST_PP_WHILE even though it doesn't - reenter BOOST_PP_WHILE by concatenating the state to BOOST_PP_WHILE_. -
-
- To accomplish this, the library uses a "trick."  - Despite what it looks like, the macro BOOST_PP_WHILE does not take three arguments.  - In fact, it takes no arguments at all.  - Instead, the BOOST_PP_WHILE macro expands to a macro that takes three arguments.  - It simply detects what the next available BOOST_PP_WHILE_ ## d macro is and returns it.  - This detection process is somewhat involved, so I won't go into how it works here, - but suffice to say it does work. -
-
- Using automatic recursion to reenter various sets of macros is obviously much simpler.  - It completely hides the underlying implementation details.  - So, if it is so much easier to use, why do the state parameters still exist?  - The reason is simple as well.  - When state parameters are used, the state is known at all times.  - This is not the case when automatic recursion is used.  - The automatic recursion mechanism has to deduce the state at each point that it is used.  - This implies a cost in macro complexity that in some situations--notably at deep macro depths--will slow - some preprocessors to a crawl. -
-

Conclusion

-
- It is really a tradeoff whether to use state parameters or automatic recursion for reentrancy.  - The strengths of automatic recursion are ease of use and implementation encapsulation.  - These come at a performance cost on some preprocessors in some situations.  - The primary strength of state parameters, on the other hand, is efficiency.  - Use of the state parameters is the only way to achieve maximum efficiency.  - This efficiency comes at the cost of both code complexity and exposition of implementation. -
-

See Also

- -
- Paul Mensonides
- +
+
+
+ There are a couple things to note in the above implementation.  First, + note how ADD_D reenters BOOST_PP_WHILE using the d state + parameter.  Second, note how MUL's operation, which is + expanded by BOOST_PP_WHILE, passes the state on to ADD_D.  + This illustrates state reentrance by both argument and concatenation. +
+
+ For every macro in the library that uses BOOST_PP_WHILE, there is a + state reentrant variant.  If that variant uses an argument rather than + concatenation, it is suffixed by _D to symbolize its method of + reentrance.  Examples or this include the library's own BOOST_PP_ADD_D + and BOOST_PP_MUL_D.  If the variant uses concatenation, it is + suffixed by an underscore.  It is completed by concatenation of the + state.  This includes BOOST_PP_WHILE itself with BOOST_PP_WHILE_ + ## d and, for example, BOOST_PP_LIST_FOLD_LEFT with BOOST_PP_LIST_FOLD_LEFT_ + ## d. +
+
+ The same seq of conventions are used for BOOST_PP_FOR and BOOST_PP_REPEAT, + but with the letters R and Z, respectively, to symbolize their + states. +
+
+ Also note that the above MUL implementation, though not + immediately obvious, is using all three types of reentrance.  Not + only is it using both types of state reentrance, it is also using automatic + recursion.... +
+

+ Automatic Recursion +

+
+ Automatic recursion is a technique that vastly simplifies the use of reentrant + constructs.  It is used by simply not using any state parameters at + all. +
+
+ The MUL example above uses automatic recursion when it uses BOOST_PP_WHILE + by itself.  In other words, MUL can still be used + inside BOOST_PP_WHILE even though it doesn't reenter BOOST_PP_WHILE + by concatenating the state to BOOST_PP_WHILE_. +
+
+ To accomplish this, the library uses a "trick."  Despite what it looks + like, the macro BOOST_PP_WHILE does not take three arguments.  In + fact, it takes no arguments at all.  Instead, the BOOST_PP_WHILE macro + expands to a macro that takes three arguments.  It simply detects + what the next available BOOST_PP_WHILE_ ## d macro is and returns + it.  This detection process is somewhat involved, so I won't go into how + it works here, but suffice to say it does work. +
+
+ Using automatic recursion to reenter various seqs of macros is obviously much + simpler.  It completely hides the underlying implementation details.  + So, if it is so much easier to use, why do the state parameters still + exist?  The reason is simple as well.  When state parameters are + used, the state is known at all times.  This is not the case when + automatic recursion is used.  The automatic recursion mechanism has to deduce + the state at each point that it is used.  This implies a cost in macro + complexity that in some situations--notably at deep macro depths--will slow + some preprocessors to a crawl. +
+

+ Conclusion +

+
+ It is really a tradeoff whether to use state parameters or automatic recursion + for reentrancy.  The strengths of automatic recursion are ease of use and + implementation encapsulation.  These come at a performance cost on some + preprocessors in some situations.  The primary strength of state + parameters, on the other hand, is efficiency.  Use of the state parameters + is the only way to achieve maximum efficiency.  This efficiency + comes at the cost of both code complexity and exposition of implementation. +
+

+ See Also +

+ +
+ - Paul Mensonides +
+