From 6978c83372b87ab163818f4e0e8b3d18fc8237be Mon Sep 17 00:00:00 2001 From: Edward Diener Date: Thu, 5 Dec 2013 17:43:48 -0500 Subject: [PATCH] Explanations about using tuples rather than arrays with variadic macro support. --- doc/data/arrays.html | 96 +++---- doc/data/tuples.html | 73 +++-- doc/topics/variadic_macros.html | 477 ++++++++++++++++---------------- 3 files changed, 324 insertions(+), 322 deletions(-) diff --git a/doc/data/arrays.html b/doc/data/arrays.html index ddbf517..181014e 100644 --- a/doc/data/arrays.html +++ b/doc/data/arrays.html @@ -1,53 +1,47 @@ - - arrays.html - - - -

Arrays

-
- An array is a data structure consisting of a two-element tuple.  - The first element is the number of elements in the array.  - The second element is another tuple of the elements in the array.  - For example, -
-
- (3, (a, b, c)) -
-
- ...is an array of 3 elements--a, b, and c. -
-
- The primary strength of arrays is that they store their own size.  - Because of this, access to elements does not require the size.  - It only requires that an element exists at a certain index. -
-
- This allows macro parameters to be variable in size and allows data states to change - size without the user explicitly keeping track of the size independently. -
-
- Elements of an array can be extracted with BOOST_PP_ARRAY_ELEM, - an array's size can be extracted with BOOST_PP_ARRAY_SIZE, and - an array can be converted to the more primitive tuple data structure - with BOOST_PP_ARRAY_DATA. -
-

Primitives

- -
-
- © Copyright Housemarque Oy 2002 -
© Copyright Paul Mensonides 2002 -
-
-

Distributed under the Boost Software License, Version 1.0. (See - accompanying file LICENSE_1_0.txt or - copy at www.boost.org/LICENSE_1_0.txt)

-
- + + arrays.html + + + +

Arrays

+
An array is a data structure consisting of a two-element tuple.  + The first element is the number of elements in the array.  + The second element is another tuple of the elements in the array.  + For example,
+
(3, (a, b, c))
+
...is an array of 3 elements--a, b, and + c.
+
The primary strength of arrays is that they store their own + size.  Because of this, access to elements does not require the + size.  It only requires that an element exists at a certain index.
+
This allows macro parameters to be variable in size and allows data + states to change size without the user explicitly keeping track of the + size independently.
+
With variadic macro support a tuple has all of the + functionality as an array, knows its own size, and is easier + syntactically to use. Because of that an array should be used, as + opposed to a tuple, only if your compiler does not support + variadic macros.
+
+ Elements of an array can be extracted with BOOST_PP_ARRAY_ELEM, + an array's size can be extracted with BOOST_PP_ARRAY_SIZE, + and an array can be converted to the more primitive tuple + data structure with BOOST_PP_ARRAY_DATA.
+

Primitives

+ +
+
© Copyright Housemarque Oy 2002
+ © Copyright Paul Mensonides 2002
+
+

Distributed under the Boost Software License, Version 1.0. (See + accompanying file LICENSE_1_0.txt + or copy at www.boost.org/LICENSE_1_0.txt)

+
+ diff --git a/doc/data/tuples.html b/doc/data/tuples.html index 38b6d5c..4b5bbea 100644 --- a/doc/data/tuples.html +++ b/doc/data/tuples.html @@ -1,42 +1,35 @@ - - tuples.html - - - -

Tuples

-
- A tuple is a simple comma-separated list of elements inside parenthesis.  - For example, -
-
- (a, b, c) -
-
- ...is a tuple of 3 elements--a, b, and c. -
-
- Tuples are fast and easy to use.  - However, all access to tuples requires knowledge of its size. -
-
- Elements of a tuple can be extracted with - BOOST_PP_TUPLE_ELEM. -
-

Primitives

- -
-
- © Copyright Housemarque Oy 2002 -
© Copyright Paul Mensonides 2002 -
-
-

Distributed under the Boost Software License, Version 1.0. (See - accompanying file LICENSE_1_0.txt or - copy at www.boost.org/LICENSE_1_0.txt)

-
- + + tuples.html + + + +

Tuples

+
A tuple is a simple comma-separated list of elements inside + parenthesis.  For example,
+
(a, b, c)
+
...is a tuple of 3 elements--a, b, and + c.
+
Tuples are fast and easy to use.  With variadic macro + support it is not necessary to know the size of a tuple; without + variadic macro support all access to tuples requires + knowledge of its size. Use a tuple instead of an array if + your compiler supports variadic macros, since a tuple has all of + the functionality as an array and is easier syntactically to use.
+
Elements of a tuple can be extracted with BOOST_PP_TUPLE_ELEM. +
+

Primitives

+ +
+
© Copyright Housemarque Oy 2002
+ © Copyright Paul Mensonides 2002
+
+

Distributed under the Boost Software License, Version 1.0. (See + accompanying file LICENSE_1_0.txt + or copy at www.boost.org/LICENSE_1_0.txt)

+
+ diff --git a/doc/topics/variadic_macros.html b/doc/topics/variadic_macros.html index 3794db1..4427765 100644 --- a/doc/topics/variadic_macros.html +++ b/doc/topics/variadic_macros.html @@ -7,235 +7,250 @@ -

Variadic Macros

-
Variadic macros are supported by a number of compilers. -They are -macros of the form: -
-
-
#define SOME_MACRO(ZeroOrMoreParameters,...) macro expansion possible specifying __VA_ARGS__
-
-
The '...' in the parameter list represents the variadic -data when the macro is invoked and the __VA_ARGS__ in the expansion -represents the variadic data in the expansion of the macro. Variadic -data is of the form of 1 or more preprocessor tokens separated by -commas.
-
-The '...' must be the last parameter in the macro definition and there -may be 0 or more non-variadic parameters preceding it.
-
-In the expansion of the macro __VA_ARGS__ may be specified 0 or more -times to represent the variadic data. The variadic data in the -expansion is a comma separated list of preprocessor tokens representing -the variadic data which the invoker of the macro enters as the last -arguments to the macro.
-
-

Example - Creating and invoking a variadic macro.

-
-
#define INITIALIZE_INT_ARRAY(array_name,...) \ 
static int array_name[] = { __VA_ARGS__ }; \
/**/

INITIALIZE_INT_ARRAY(myname,45,789,33510,9346,2)
-
- Preprocessor -Library Support
-
-
The library offers support for variadic macros for those -compilers -which support the feature. The library can automatically detect whether -a compiler supports variadic macros and sets the macro -BOOST_PP_VARIADICS accordingly to 1 if the compiler supports variadic -macros or 0 if the compiler does not support variadic macros.
-
-The end-user can #define BOOST_PP_VARIADICS to 1 or 0 himself in a -translation unit, before including any preprocessor header files, to -prevent the library from attempting to detect whether the compiler -supports variadic macros. This has the effect of manually turning on or -off variadic macro support in the library. Of course if one manually -turns on variadic macro support in the library, and one's compiler does -not support variadic macros, functionality in the library which uses -variadic macros will fail with error messages from the compiler.
-
-When BOOST_PP_VARIADICS is 1, the library offers some extended -functionality -by using variadic macros, and also offers extended support for working -with variadic data.
-
-Support for working with variadic -data is largely centered on being able to convert variadic data to -other library data types, since the -functionality for working with those Boost preprocessor library data -types is much greater than that for working with variadic data directly.
-
- -

Notation For Variadic Macros
-

-
In the documentation, headers which have variadic macros, -and -variadic macros themselves, have a notation of '(v)' appended to them. -For the variadic macros themselves this signifies that -BOOST_PP_VARIADICS must be 1 for those variadic macros to be usable. -For variadic macros which have a non-variadic equivalent, the -non-variadic equivalent will be used if BOOST_PP_VARIADICS is set to 0. -
-

Extended Functionality Using Variadic Macros
-

-
Some macros in the library offer extended -functionality through the use of variadic macros.
-
-The variadic macro version offers the same functionality -as the non-variadic version, but because of the ability of the variadic -parameters to encompass a variable number of arguments, it also offers -an enhanced syntax using the same macro name.
-
-The macros in the library which offer this enhanced functionality are -all -centered on tuple manipulation. With variadic -macros it is -possible to -manipulate tuples without having to know the size of the tuple. So -while the invoker can still specify the size when using tuple macro -functionality, there are variadic versions of each of the tuple macros, -with the exact same name as the non-variadic macro, where the size need -not be specified.
-
-

Extended Support For Variadic Data

-
The library offers extended support for working with -variadic data -which goes beyond the functionality offered by the C++ specification -for variadic macros. It does this through preprocessor programming and -by using some of the other functionality in the library itself. Header -and macro names -in the library which offer extended support for working with variadic -data, and need the compiler to support variadic macros, are marked with -a (v) to indicate a variadic macro.
-
-The form of the functionality which the library offers is centered on -two macros which work with variadic data itself, and a set of macros -which convert between variadic data and other library data -types.
-
-The two macros are BOOST_PP_VARIADIC_ELEM and BOOST_PP_VARIADIC_SIZE, -which respectively return a particular token of variadic data and the -number of tokens of variadic data.
-
-The macros for converting variadic data to the library's data types are -BOOST_PP_VARIADIC_TO_ARRAY, BOOST_PP_VARIADIC_TO_LIST, -BOOST_PP_VARIADIC_TO_SEQ, and BOOST_PP_VARIADIC_TO_TUPLE.
-
-All of these macros need compiler support for variadic data and only -exist if BOOST_PP_VARIADICS is 1.
-
-The remaining four macros, which convert from a library data type -to comma-separated preprocessor tokens, which is the form of -variadic data, do not need compiler support for variadic -macros. These functions are BOOST_PP_ARRAY_ENUM, BOOST_PP_LIST_ENUM, -BOOST_PP_SEQ_ENUM, and BOOST_PP_TUPLE_ENUM. However if one wishes to -use this variadic data reliably as arguments to other macros, one needs -variadic macro support.
-
- Using Variadic Data -
Variadic data exists in the -form of comma-separated preprocessor tokens. This is the case whether -the variadic data comes from the __VA_ARGS__ of a variadic macro, from -the conversion of a library's data type to variadic data, or the -manual construction of comma-separated preprocessing tokens by the -programmer writing a macro.
-
-The easiest way to work with -variadic data internally is to convert it to a library data type. -Library data types, whether an array, list, -sequence, -or tuple, have a rich set of functionality for -manipulating -data whereas -variadic data functionality in the library only allows one to access -the variadic data as a whole or to access a single token of the -variadic data at a time.
-
-The user of the library still may -choose to pass variadic data back into internal macros rather than -convert it to other library data types. There is no problem passing -variadic data as a whole to variadic macros as the last parameter of -the macro. However:
-
-Attempting to pass -variadic data as a -whole directly into a non-variadic macro is not guaranteed to work and -may fail.
-

-This occurs because of a preprocessor weakness in a number -of compilers, currently most notably Visual C++. Even passing variadic -data as arguments to a non-variadic macro, when it is not represented -in -the form of  __VA_ARGS__, may fail with certain compilers.
-
-What follows are very simple examples, showing how variadic data can be -passed to a non-variadic macro.
-
-First an example of what NOT to do.
-
-

Example - Passing variadic data as a whole to a -non-variadic -macro. DO NOT DO.

-
-
#define MACRO_ARG_2(x,y) BOOST_PP_ADD(x,y)
#define VAR_MACRO(...) __VA_ARGS__

/* The following should not be done and is not guaranteed to work with compilers. */

int xx = MACRO_ARG_2(VAR_MACRO(2,3));
-
-
There are two ways to pass variadic data to a non-variadic -macro. -The -first of these is to pass the individual tokens of the variadic data -separately to the non-variadic macro using the BOOST_PP_VARIADIC_ELEM -macro in the library.
-
-

Example - Passing individual variadic data tokens to -a -non-variadic macro.
-

-
-
#define MACRO_ARG_2(x,y) BOOST_PP_ADD(x,y)
#define VAR_MACRO(...) __VA_ARGS__

/* The following will work correctly */

int xx = MACRO_ARG_2
(
BOOST_PP_VARIADIC_ELEM(0,VAR_MACRO(2,3)),
BOOST_PP_VARIADIC_ELEM(1,VAR_MACRO(2,3))
);
-
-
The second way is to use a macro in the library called -BOOST_PP_OVERLOAD. -This macro allows one to "overload" a variadic macro to non-variadic -macros of different numbers of parameters, using a common prefix. -
-

Example - Passing variadic data as a whole to -BOOST_PP_OVERLOAD -and on to a non-variadic macro.
-

-
-
#define MACRO_ARG_2(x,y) BOOST_PP_ADD(x,y)
#define VAR_MACRO(...) __VA_ARGS__

/* The following will work correctly */

int xx = BOOST_PP_OVERLOAD(MACRO_ARG_,VAR_MACRO(2,3))(VAR_MACRO(2,3));

/* For Visual C++ it is necessary to do this */

int xx =
BOOST_PP_CAT(BOOST_PP_OVERLOAD(MACRO_ARG_,VAR_MACRO(2,3))(VAR_MACRO(2,3)),BOOST_PP_EMPTY());
-

-
Although these techniques will work when passing variadic -data to -non-variadic macros, it is much better and less problematical to -work internally with the existing library data types and to only use -variadic -macros as an interface for end-users when there is a need to have a -macro which takes a -variable number of parameters.
-
-See Also
- -
-
© Copyright -Edward Diener -2011,2013
-
-

Distributed under the Boost Software License, -Version 1.0. -(See accompanying file LICENSE_1_0.txt -or copy at www.boost.org/LICENSE_1_0.txt)

-
+

Variadic Macros

+
Variadic macros are supported by a number of compilers. + They are + macros of the form: +
+
+
#define SOME_MACRO(ZeroOrMoreParameters,...) macro expansion possible specifying __VA_ARGS__
+
+
The '...' in the parameter list represents the variadic + data when the macro is invoked and the __VA_ARGS__ in the expansion + represents the variadic data in the expansion of the macro. Variadic + data is of the form of 1 or more preprocessor tokens separated by + commas.
+
+ The '...' must be the last parameter in the macro definition and there + may be 0 or more non-variadic parameters preceding it.
+
+ In the expansion of the macro __VA_ARGS__ may be specified 0 or more + times to represent the variadic data. The variadic data in the + expansion is a comma separated list of preprocessor tokens representing + the variadic data which the invoker of the macro enters as the last + arguments to the macro.
+
+

Example - Creating and invoking a variadic macro.

+
+
#define INITIALIZE_INT_ARRAY(array_name,...) \ 
static int array_name[] = { __VA_ARGS__ }; \
/**/

INITIALIZE_INT_ARRAY(myname,45,789,33510,9346,2)
+
+ Preprocessor + Library Support
+
+
The library offers support for variadic macros for those + compilers + which support the feature. The library can automatically detect whether + a compiler supports variadic macros and sets the macro + BOOST_PP_VARIADICS accordingly to 1 if the compiler supports variadic + macros or 0 if the compiler does not support variadic macros.
+
+ The end-user can #define BOOST_PP_VARIADICS to 1 or 0 himself in a + translation unit, before including any preprocessor header files, to + prevent the library from attempting to detect whether the compiler + supports variadic macros. This has the effect of manually turning on or + off variadic macro support in the library. Of course if one manually + turns on variadic macro support in the library, and one's compiler does + not support variadic macros, functionality in the library which uses + variadic macros will fail with error messages from the compiler.
+
+ When BOOST_PP_VARIADICS is 1, the library offers some extended + functionality + by using variadic macros, and also offers extended support for working + with variadic data.
+
+ Support for working with variadic + data is largely centered on being able to convert variadic data to + other library data types, since the + functionality for working with those Boost preprocessor library data + types is much greater than that for working with variadic data directly.
+
+ +

Notation For Variadic Macros
+

+
In the documentation, headers which have variadic macros, + and + variadic macros themselves, have a notation of '(v)' appended to them. + For the variadic macros themselves this signifies that + BOOST_PP_VARIADICS must be 1 for those variadic macros to be usable. + For variadic macros which have a non-variadic equivalent, the + non-variadic equivalent will be used if BOOST_PP_VARIADICS is set to 0. +
+

Extended Functionality Using Variadic Macros
+

+
Some macros in the library offer extended + functionality through the use of variadic macros.
+
+ The variadic macro version offers the same functionality + as the non-variadic version, but because of the ability of the variadic + parameters to encompass a variable number of arguments, it also offers + an enhanced syntax using the same macro name.
+
+ The macros in the library which offer this enhanced functionality are + all + centered on tuple manipulation. With variadic + macros it is + possible to + manipulate tuples without having to know the size of the tuple. So + while the invoker can still specify the size when using tuple macro + functionality, there are variadic versions of each of the tuple macros, + with the exact same name as the non-variadic macro, where the size need + not be specified.
+
+

Extended Support For Variadic Data

+
The library offers extended support for working with + variadic data + which goes beyond the functionality offered by the C++ specification + for variadic macros. It does this through preprocessor programming and + by using some of the other functionality in the library itself. Header + and macro names + in the library which offer extended support for working with variadic + data, and need the compiler to support variadic macros, are marked with + a (v) to indicate a variadic macro.
+
+ The form of the functionality which the library offers is centered on + two macros which work with variadic data itself, and a set of macros + which convert between variadic data and other library data + types.
+
+ The two macros are BOOST_PP_VARIADIC_ELEM and BOOST_PP_VARIADIC_SIZE, + which respectively return a particular token of variadic data and the + number of tokens of variadic data.
+
+ The macros for converting variadic data to the library's data types are + BOOST_PP_VARIADIC_TO_ARRAY, BOOST_PP_VARIADIC_TO_LIST, + BOOST_PP_VARIADIC_TO_SEQ, and BOOST_PP_VARIADIC_TO_TUPLE.
+
+ All of these macros need compiler support for variadic data and only + exist if BOOST_PP_VARIADICS is 1.
+
+ The remaining four macros, which convert from a library data type + to comma-separated preprocessor tokens, which is the form of + variadic data, do not need compiler support for variadic + macros. These functions are BOOST_PP_ARRAY_ENUM, BOOST_PP_LIST_ENUM, + BOOST_PP_SEQ_ENUM, and BOOST_PP_TUPLE_ENUM. However if one wishes to + use this variadic data reliably as arguments to other macros, one needs + variadic macro support.
+
+ Using a Tuple Instead of an Array
+
+
An array as a preprocessor data type is a two-element tuple where the + first element is the array size and the second element is a tuple which + constitutes the array data. Because a tuple knows its own size when the + compiler supports variadic macros, there is no reason to use the array preprocessor + data type as opposed to the tuple preprocessor data type; the tuple data + type now has all of the functionality which the array data type has and is + syntactically easier to use. With variadic macro support, which is now + officially part of the latest C++ standard, the preprocessor array data + type is essentially obsolete for conforming C++ compilers. Only if your + compiler does not support variadic macros is the preprocessor array data + type still useful.
+ Using Variadic Data +
Variadic data exists in the + form of comma-separated preprocessor tokens. This is the case whether + the variadic data comes from the __VA_ARGS__ of a variadic macro, from + the conversion of a library's data type to variadic data, or the + manual construction of comma-separated preprocessing tokens by the + programmer writing a macro.
+
+ The easiest way to work with + variadic data internally is to convert it to a library data type. + Library data types, whether an array, list, + sequence, + or tuple, have a rich set of functionality for + manipulating + data whereas + variadic data functionality in the library only allows one to access + the variadic data as a whole or to access a single token of the + variadic data at a time.
+
+ The user of the library still may + choose to pass variadic data back into internal macros rather than + convert it to other library data types. There is no problem passing + variadic data as a whole to variadic macros as the last parameter of + the macro. However:
+
+ Attempting to pass + variadic data as a + whole directly into a non-variadic macro is not guaranteed to work and + may fail.
+

+ This occurs because of a preprocessor weakness in a number + of compilers, currently most notably Visual C++. Even passing variadic + data as arguments to a non-variadic macro, when it is not represented + in + the form of  __VA_ARGS__, may fail with certain compilers.
+
+ What follows are very simple examples, showing how variadic data can be + passed to a non-variadic macro.
+
+ First an example of what NOT to do.
+
+

Example - Passing variadic data as a whole to a + non-variadic + macro. DO NOT DO.

+
+
#define MACRO_ARG_2(x,y) BOOST_PP_ADD(x,y)
#define VAR_MACRO(...) __VA_ARGS__

/* The following should not be done and is not guaranteed to work with compilers. */

int xx = MACRO_ARG_2(VAR_MACRO(2,3));
+
+
There are two ways to pass variadic data to a non-variadic + macro. + The + first of these is to pass the individual tokens of the variadic data + separately to the non-variadic macro using the BOOST_PP_VARIADIC_ELEM + macro in the library.
+
+

Example - Passing individual variadic data tokens to + a + non-variadic macro.
+

+
+
#define MACRO_ARG_2(x,y) BOOST_PP_ADD(x,y)
#define VAR_MACRO(...) __VA_ARGS__

/* The following will work correctly */

int xx = MACRO_ARG_2
(
BOOST_PP_VARIADIC_ELEM(0,VAR_MACRO(2,3)),
BOOST_PP_VARIADIC_ELEM(1,VAR_MACRO(2,3))
);
+
+
The second way is to use a macro in the library called + BOOST_PP_OVERLOAD. + This macro allows one to "overload" a variadic macro to non-variadic + macros of different numbers of parameters, using a common prefix. +
+

Example - Passing variadic data as a whole to + BOOST_PP_OVERLOAD + and on to a non-variadic macro.
+

+
+
#define MACRO_ARG_2(x,y) BOOST_PP_ADD(x,y)
#define VAR_MACRO(...) __VA_ARGS__

/* The following will work correctly */

int xx = BOOST_PP_OVERLOAD(MACRO_ARG_,VAR_MACRO(2,3))(VAR_MACRO(2,3));

/* For Visual C++ it is necessary to do this */

int xx =
BOOST_PP_CAT(BOOST_PP_OVERLOAD(MACRO_ARG_,VAR_MACRO(2,3))(VAR_MACRO(2,3)),BOOST_PP_EMPTY());
+
+
+
Although these techniques will work when passing variadic + data to + non-variadic macros, it is much better and less problematical to + work internally with the existing library data types and to only use + variadic + macros as an interface for end-users when there is a need to have a + macro which takes a + variable number of parameters.
+
+ See Also
+ +
+
© Copyright + Edward Diener + 2011,2013
+
+

Distributed under the Boost Software License, + Version 1.0. + (See accompanying file LICENSE_1_0.txt + or copy at www.boost.org/LICENSE_1_0.txt)

+
- \ No newline at end of file +