- The BOOST_PP_LIST_ENUM macro converts a list to a comma-separated list.
-
-
Usage
-
- BOOST_PP_LIST_ENUM(list)
-
-
Arguments
-
-
list
-
- The list to be converted.
-
-
-
Remarks
-
- If list is, for example, (a, (b, (c, BOOST_PP_NIL))),
- this macro will produce:
-
- a, b, c
-
-
-
- Previously, this macro could not be used inside BOOST_PP_FOR.
- There is no longer any such restriction.
- It is more efficient, however, to use BOOST_PP_LIST_ENUM_R in such a situation.
-
The BOOST_PP_LIST_ENUM macro
+ converts a list to a comma-separated list.
+
Usage
+
BOOST_PP_LIST_ENUM(list)
+
Arguments
+
+
list
+
The list to be converted.
+
+
Remarks
+
If list is, for example, (a, (b, (c,
+ BOOST_PP_NIL))), this macro will produce:
+
a, b, c
+
+
Previously, this macro could not be used inside BOOST_PP_FOR.
+
+ There is no longer any such restriction. It is more
+ efficient, however, to use BOOST_PP_LIST_ENUM_R in such a
+ situation.
+
+ In C++
+ 20 mode if the list is empty the resulting variadic
+ data will be empty.
Variadic macros are supported by a number of compilers. They are
- macros of the form:
-
+
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 '...' 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.
+ 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.
+ 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.
- Preprocessor
- Library Support
+ 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.
+ 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.
+ 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.
- Visual C++ has a
- few quirks related to variadic macros which require the end-user to code
- slightly differently. When BOOST_PP_VARIADICS is 1 and Visual C++ is the
- compiler BOOST_PP_VARIADICS_MSVC is 1, else when BOOST_PP_VARIADICS is 1
- and Visual C++ is not the compiler BOOST_PP_VARIADICS_MSVC is 0. When
- BOOST_PP_VARIADICS is 0 then BOOST_PP_VARIADICS_MSVC is not defined.
- In this way the end-user, when using variadic macros, can test for the
- presence of Visual C++ as the compiler and code accordingly.
+ 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.
+ Visual C++ has a few quirks related to
+ variadic macros which require the end-user to code slightly
+ differently. When BOOST_PP_VARIADICS is 1 and Visual C++ is the
+ compiler BOOST_PP_VARIADICS_MSVC is 1, else when
+ BOOST_PP_VARIADICS is 1 and Visual C++ is not the compiler
+ BOOST_PP_VARIADICS_MSVC is 0. When BOOST_PP_VARIADICS is 0 then
+ BOOST_PP_VARIADICS_MSVC is not defined. In this way the end-user,
+ when using variadic macros, can test for the presence of Visual
+ C++ as the compiler and code accordingly.
+
+ 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.
-
+
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.
+
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 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.
+ 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 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
+ 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 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,
+ 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.
+ 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.
+ 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.
-
C++20 Support For Variadic Macros
-
- In the C++20 specification there is a new construct which can be
- used in the expansion of a variadic macro, called __VA_OPT__. This
- construct when used in the expansion of a variadic macro is followed
- by an opening paranthesis ('('), preprocessor data, and a closing
- parenthesis ('}'). When the variadic data passed by the invocation
- of a variadic macro is empty, this new construct expands to nothing.
- When the variadic data passed by the invocation of a variadic macro
- is not empty, this new construct expands to the preprocessor data
- between its opening and closing parentheses.
-
- This library offers support for this new C++20 construct by automatically
- detecting whether this new construct is supported by the compiler's
- preprocessor when using the library. The library macro which detects
- support for the __VA_OPT__ construct is called BOOST_PP_VARIADIC_HAS_OPT.
- This is a function-like macro which takes no parameters and returns
- 1 if the compiler is working in C++20 mode and supports the __VA_OPT__
- construct, while otherwise it returns 0.
+
C++20 Support For
+ Variadic Macros
+
In the C++20 specification there is a new construct which can
+ be used in the expansion of a variadic macro, called __VA_OPT__.
+ This construct when used in the expansion of a variadic macro is
+ followed by an opening paranthesis ('('), preprocessor data, and a
+ closing parenthesis ('}'). When the variadic data passed by the
+ invocation of a variadic macro is empty, this new construct
+ expands to nothing. When the variadic data passed by the
+ invocation of a variadic macro is not empty, this new construct
+ expands to the preprocessor data between its opening and closing
+ parentheses.
+ This library offers support for this new C++20 construct by
+ automatically detecting whether this new construct is supported by
+ the compiler's preprocessor when using the library. The library
+ macro which detects support for the __VA_OPT__ construct is called
+ BOOST_PP_VARIADIC_HAS_OPT. This is a function-like macro which
+ takes no parameters and returns 1 if the compiler is working in
+ C++20 mode and supports the __VA_OPT__ construct, while otherwise
+ it returns 0.
+
+ When the __VA_OPT__ construct is supported in C++20 mode the
+ variadic data passed to the variadic macros can be empty,
+ otherwise when not in this mode variadic data passed to the
+ variadic macros should never be empty. In this C+++20 mode
+ invoking BOOST_PP_VARIADIC_SIZE with empty data expands to 0,
+ invoking BOOST_PP_VARIADIC_TO_ARRAY with empty data expands to the
+ empty array '(0,())', and invoking BOOST_PP_VARIADIC_TO_LIST with
+ empty data expands to the empty list 'BOOST_PP_NIL'. Similarly in
+ this C++20 mode passing an empty array '(0,())' to
+ BOOST_PP_ARRAY_ENUM expands to empty variadic data and passing an
+ empty list 'BOOST_PP_NIL' to BOOST_PP_LIST_ENUM also expands to
+ empty variadic data. Neither a seq or a tuple can be empty so
+ passing empty variadic data to either BOOST_PP_VARIADIC_TO_SEQ or
+ BOOST_PP_VARIADIC_TO_TUPLE is erroneous. Likewise passing empty
+ data to BOOST_PP_VARIADIC_ELEM is always erroneous since there are
+ no tokens of variadic data to access.
- Using a Tuple Instead of an Array
+ 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
+
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 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:
+ 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.
+ 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.
+ 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.
+ 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
+
Example - Passing variadic data as a whole to a non-variadic
macro. DO NOT DO.
/* 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.
+ 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
+
Example - Passing individual variadic data tokens to a
non-variadic macro.
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.
-
+ 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.
+ BOOST_PP_OVERLOAD and on to a non-variadic macro.
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.
+
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.