@@ -19,10 +20,10 @@
Contents
-
+
- Motivation
- Preprocessor Metaprogramming Techniques
-
+
- Use a Local Macro to avoid small scale repetition
- Use BOOST_PP_EMPTY as an unused parameter in Local
Macro instantiations
@@ -53,8 +54,7 @@
must be overloaded for every distinct number of parameters that is to be supported.
Example:
-
- template <class R>
+template <class R>
yes_type is_function_tester(R (*)());
template <class R, class A0>
yes_type is_function_tester(R (*)(A0));
@@ -65,7 +65,6 @@ yes_type is_function_tester(R (*)(A0, A1, A2));
// ...
-
The need for this kind of repetition occurs particularly frequently while implementing
generic components or metaprogramming facilities, but the need also manifests
@@ -108,15 +107,14 @@ yes_type is_function_tester(R (*)(A0, A1, A2));
Using the primitives of the PREPROCESSOR library, the is_function_tester()s
could be implemented like this:
-
- #define IS_FUNCTION_TESTER(N,_)\
+#define IS_FUNCTION_TESTER(N,_)\
template<class R BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_PARAMS(N, class A)>\
yes_type is_function_tester(R (*)(BOOST_PP_ENUM_PARAMS(N,A)));
BOOST_PP_REPEAT_2ND(BOOST_PP_INC(MAX_IS_FUNCTION_TESTER_PARAMS),IS_FUNCTION_TESTER,_)
#undef IS_FUNCTION_TESTER
-
+
In order to change the maximum number of function parameters supported, you
now simply change the MAX_IS_FUNCTION_TESTER_PARAMS definition and recompile.
@@ -128,8 +126,7 @@ BOOST_PP_REPEAT_2ND(BOOST_PP_INC(MAX_IS_FUNCTION_TESTER_PARAMS),IS_FUNCTION_TEST
EXAMPLE:
Use a Local Macro to avoid small scale repetition
-
- #define BOOST_PP_DEF(OP) \
+#define BOOST_PP_DEF(OP) \
template<class T, int n> \
vec<T,n>& \
operator OP##= \
@@ -149,7 +146,6 @@ BOOST_PP_DEF(*)
BOOST_PP_DEF(/)
#undef BOOST_PP_DEF
-
TIP: It is usually okay to use a standard macro name like BOOST_PP_DEF
for this kind of code, because the macro is both defined and undefined in the
@@ -167,8 +163,7 @@ the line continuation operator when they are aligned.
EXAMPLE:
Use BOOST_PP_EMPTY as an unused parameter in Local Macro instantiations
-
- #define BOOST_PP_DEF(CV) \
+#define BOOST_PP_DEF(CV) \
template<class base> \
CV() typename implement_subscript_using_begin_subscript<base>::value_type&\
implement_subscript_using_begin_subscript<base>::operator[]\
@@ -182,7 +177,6 @@ BOOST_PP_DEF(BOOST_PP_EMPTY)
BOOST_PP_DEF(const BOOST_PP_EMPTY)
#undef BOOST_PP_DEF
-
HOW: BOOST_PP_EMPTY() expands to nothing and can be used as
an unused parameter.
@@ -206,8 +200,7 @@ of the line continuation operators without making the code too unreadable.
EXAMPLE: Use BOOST_PP_CAT instead of ## when necessary
-
- #define STATIC_ASSERT(EXPR)\
+#define STATIC_ASSERT(EXPR)\
enum\
{ BOOST_PP_CAT(static_check_,__LINE__) = (EXPR) ? 1 : -1\
};\
@@ -220,22 +213,21 @@ of the line continuation operators without making the code too unreadable.
STATIC_ASSERT(sizeof(int) <= sizeof(long));
-
WHY: Macro expansion proceeds recursively in "layers". Token pasting
prevents the preprocessor from performing macro expansion, therefore it
is often necessary to delay token concatenation.
EXAMPLE: Use BOOST_PP_STRINGIZE instead of # whenever necessary
-
- #define NOTE(STR)\
+
+#define NOTE(STR)\
message(__FILE__ "(" BOOST_PP_STRINGIZE(__LINE__) ") : " STR)
// ...
#pragma NOTE("TBD!")
-
+
WHY: Macro expansion proceeds recursively in "layers". Stringization
prevents the preprocessor from performing macro expansion, therefore it is often
necessary to delay stringization.
@@ -251,8 +243,8 @@ STATIC_ASSERT(sizeof(int) <= sizeof(long));
BOOST_PP_COMMA_IF
to avoid O(N) repetition on lists in general
-
- struct make_type_list_end;
+
+struct make_type_list_end;
template
< BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT
@@ -290,12 +282,10 @@ public:
>::type type;
};
-
HOW: BOOST_PP_REPEAT uses simulated recursion (pseudo code):
-
- #define BOOST_PP_REPEAT(N,M,P) BOOST_PP_REPEAT##N(M,P)
+#define BOOST_PP_REPEAT(N,M,P) BOOST_PP_REPEAT##N(M,P)
#define BOOST_PP_REPEAT0(M,P)
#define BOOST_PP_REPEAT1(M,P) M(0,P)
#define BOOST_PP_REPEAT2(M,P) M(0,P) M(1,P)
@@ -303,7 +293,6 @@ public:
#define BOOST_PP_REPEAT4(M,P) BOOST_PP_REPEAT3(M,P) M(3,P)
// ...
-
BOOST_PP_ENUM_PARAMS variations use BOOST_PP_REPEAT
@@ -318,12 +307,10 @@ public:
enable user configuration of code repetition based on need rather than some
"reasonable" upper limit
-
- #ifndef MAKE_TYPE_LIST_MAX_LENGTH
+#ifndef MAKE_TYPE_LIST_MAX_LENGTH
#define MAKE_TYPE_LIST_MAX_LENGTH 8
#endif
-
Now the user can configure the make_type_list primitive without modifying library
code.
@@ -332,8 +319,7 @@ enable user configuration of code repetition based on need rather than some
Use BOOST_PP_REPEAT and a Token Look-Up Function to eliminate categorical
repetition
-
- // CAVEAT: My compiler is not standard on arithmetic types.
+// CAVEAT: My compiler is not standard on arithmetic types.
#define ARITHMETIC_TYPE(I) ARITHMETIC_TYPE##I
#define ARITHMETIC_TYPE0 bool
#define ARITHMETIC_TYPE1 char
@@ -366,7 +352,6 @@ BOOST_PP_REPEAT
// ...
-
NOTE: The repetition of the above
example can be eliminated using template metaprogramming [Czarnecki] as well. However
@@ -376,8 +361,7 @@ using template metaprogramming.
EXAMPLE:
Use BOOST_PP_REPEAT_2ND to avoid O(N*N) repetition
-
- #ifndef MAX_VEC_ARG_CNT
+#ifndef MAX_VEC_ARG_CNT
#define MAX_VEC_ARG_CNT 8
#endif
@@ -403,8 +387,6 @@ BOOST_PP_REPEAT_2ND
// ...
-
-
HOW: BOOST_PP_REPEAT_2ND is implemented separately, so it
is possible to combine BOOST_PP_REPEAT and BOOST_PP_REPEAT_2ND.
@@ -412,14 +394,12 @@ BOOST_PP_REPEAT_2ND
EXAMPLE: Use BOOST_PP_IF to implement special case for the first element
-
- #define BOOST_PP_COMMA_IF(C)\
+#define BOOST_PP_COMMA_IF(C)\
BOOST_PP_IF(C,BOOST_PP_COMMA,BOOST_PP_EMPTY)()
BOOST_PP_IF(0,true,false) == false;
BOOST_PP_IF(1,true,false) == true;
-
BOOST_PP_IF enables convenient generation of lists using BOOST_PP_REPEAT.
@@ -428,28 +408,27 @@ BOOST_PP_IF(1,true,false) == true;
you have to make the other parameter a function-like macro, too. This can often
be done using BOOST_PP_IDENTITY. Consider the following example (by
Aleksey Gurtovoy):
-
- #define NUMBERED_EXPRESSION(I,X)\
+
+#define NUMBERED_EXPRESSION(I,X)\
BOOST_PP_IF \
( I \
, BOOST_PP_IDENTITY(X##I) \
, BOOST_PP_EMPTY \
)()
-
+
NOTE: Like in the above implementation of COMMA_IF, the result of IF
is often invoked and not the THEN and ELSE parameters. If the parameters were
invoked, the code would not expand correctly, because the EMPTY parameter would
get expanded to nothing before the IF would be properly expanded.
HOW: BOOST_PP_IF is defined for the entire repeat range (pseudo
code):
-
- #define BOOST_PP_IF(C,THEN,ELSE) BOOST_PP_IF##C(THEN,ELSE)
+
+#define BOOST_PP_IF(C,THEN,ELSE) BOOST_PP_IF##C(THEN,ELSE)
#define BOOST_PP_IF0(THEN,ELSE) ELSE
#define BOOST_PP_IF1(THEN,ELSE) THEN
#define BOOST_PP_IF2(THEN,ELSE) THEN
// ...
-
@@ -461,8 +440,7 @@ comparison operations on decimal integer literals in the range [0,BOOST_PP_LIMIT
Suppose that you want to generate a numbered lists with a special element inserted
at a desired position. For example: E0, E1, S, E2. Consider the following example:
-
- #define SPECIAL_NUMBERED_LIST(N,I,ELEM,SPECIAL)\
+#define SPECIAL_NUMBERED_LIST(N,I,ELEM,SPECIAL)\
BOOST_PP_ASSERT_MSG(BOOST_PP_LESS(I,N),BAD PARAMS FOR SPECIAL_NUMBERED_LIST!)\
BOOST_PP_ENUM_PARAMS(I,ELEM)\
BOOST_PP_COMMA_IF(I) SPECIAL\
@@ -483,7 +461,6 @@ SPECIAL_NUMBERED_LIST(3,1,E,S)
SPECIAL_NUMBERED_LIST(3,2,E,S)
SPECIAL_NUMBERED_LIST(3,3,E,S)
-
Revised
@@ -492,9 +469,9 @@ SPECIAL_NUMBERED_LIST(3,3,E,S)
© Copyright Housemarque Oy 2002
-Permission to copy, use, modify, sell and distribute this document is granted
+
Permission to copy, use, modify, sell and distribute this document is granted
provided this copyright notice appears in all copies. This document is provided
"as is" without express or implied warranty, and with no claim as to its suitability
-for any purpose.
+for any purpose.