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.
+ Given certain arguments a macro might expand to nothing, aka no preprocessor tokens. This may
+ happen more than the previous case of an argument to a macro being nothing because the expansion of a macro
+ is often used to initialize some C++ construct, and C++ has some places where
+ a part of a compile-time construct can be empty. However a macro which expands to nothing
+ rarely occurs when a macro's expansion is used as an argument to another macro, although
+ again it is perfectly legal C++.
-
#define INITIALIZE_INT_ARRAY(array_name,...) \
static int array_name[] = { __VA_ARGS__ }; \
/**/
INITIALIZE_INT_ARRAY(myname,45,789,33510,9346,2)
+
+ #define ANOTHER_MACRO(Parameter1,Parameter2) /* expands to nothing when Parameter1 and Parameter2
+ are numbers, otherwise expands to some preprocessing
+ token, such as '1' */
+
+ int another_int = { ANOTHER_MACRO(x,y) }; // ANOTHER_MACRO Expands to 1
+ int some_int = { ANOTHER_MACRO(1,2) }; // ANOTHER_MACRO Expands to nothing
+ SOME_MACRO(ANOTHER_MACRO(x,y),z) // Normal, ANOTHER_MACRO Expands to 1
+ SOME_MACRO(ANOTHER_MACRO(1,2),z) // Legal, first argument is empty as ANOTHER_MACRO Expands to nothing
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.
-
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.
+
Emptiness defined
+
+ Passing nothing as a macro argument or a macro expanding to nothing I term as 'emptiness',
+ as 'nothing' is too amorphous a term which can be used in too many other contexts for my liking.
+ In the vast majority of cases when designing a macro for use emptiness is not a part of such
+ a design, and passing emptiness as an argument or expanding to emptiness is not anything
+ that someone writing a macro takes into account when he explains to other programmers
+ how a macro should be used.
+ Other than the fact that macros are generally created so that some actual preprocessor
+ data of a particular kind needs to be passed as arguments or gets generated as part of
+ macro expansion when a macro is invoked, there is another very good reason why working
+ with emptiness is not part of a macro's design: there has been no perfectly fail-safe
+ way to test for emptiness during macro expansion, whether it be in creating macros
+ using just the facilities of the C++ standard or using a 3rd party library, such as
+ this Boost preprocessor library. When I say 'fail-safe' I mean that there has always
+ been some argument input, no matter how small the number of potential cases, where a
+ macro designed to test whether or not the preprocessor data passed to it as an argument
+ when the macro is invoked is actually empty, fails in some
+ way, with the failure normally occurring as a preprocessor error.
+ Of course this does not mean that the best macro designed to test for emptiness
+ will not work correctly the vast majority of the time. It only means that there
+ has been no guarantee that such a macro will work correctly all 100% of the time.
+ Nonetheless there have been uses of testing for emptiness, when a macro documents
+ what a particular argument should generally consist of, even if the test is not
+ guaranteed to work 100% of the time if particular unexpected argument data does get passed.
+
+
A C++20 solution for testing for emptiness
+
+ The C++ standard committee recognized, in the upcoming specification for the C++20 standard,
+ that a way of testing whether variadic data is empty or not in the expansion of a variadic
+ macro would be very useful when designing certain types of macros. Because of this
+ the C++20 standard added a preprocessor construct which could do this in a certain way
+ for variadic data in the expansion of a variadic macro.
+ The construct is called __VA_OPT__. I am not going to explain that construct here, as the
+ documentation for it is part of the upcoming C++20 standard and is readily available on
+ various C++ sites on the Internet, but the further upshot of adding the __VA_OPT__ construct
+ to C++20 is that it is now possible to create a variadic macro which is 100% reliable in
+ testing for emptiness whenever a compiler supports the __VA_OPT__ construct in its
+ compilation of preprocessor code.
+ For such a macro to always work which tests for emptiness the code must know when
+ the __VA_OPT__ construct is available. It is not enough to know that a compiler is
+ working at the C++20 level, since as all C++ programmers know an adherence to a C++ standard
+ level never guarantees that a particular compiler supports every aspect of that level.
+ Happily there is a way to test whether a compiler supports the __VA_OPT__ construct
+ as long as the compiler supports variadic macros, and that way has been openly published
+ on the Internet although the actual macro code would not have been hard to create even if it had
+ not publicly appeared. This library uses that code to test for __VA_OPT__ as a necessary prelude
+ for creating a variadic macro which is 100% reliable in testing for emptiness.
+ The Boost Preprocessor macro for testing whether the __VA_OPT__ construct is supported during
+ compilation is called BOOST_PP_VARIADIC_OPT, which is a function-like macro taking no parameters
+ and returning 1 if the __VA_OPT__ construct is supported and 0 if it is not. The macro
+ only returns 1 when variadic macros are supported, when the compiler is at the C++20 level,
+ and when the __VA_OPT__ construct can be used according to the C++20 standard. In particular
+ the macro needs the compiler to be working at the C++20 level despite the fact that at least
+ one major compiler supports the __VA_OPT__ construct in some of its latest releases even
+ when the compiler is being used at a C++ standard level below that of C++20. The reason this
+ Boost preprocessor library requires the C++20 level is because that same major compiler
+ can produce a warning, or even an error, when it even sees a macro using the __VA_OPT__
+ construct at a level below C++20, even though it supports it, if other compiler options
+ requiring strict adherence to the level of the C++ standard being used are passed on the
+ command line. So taking a conservative approach the BOOST_PP_VARIADIC_OPT macros requires
+ compilation at the C++20 level, along with variadic macro support, along with the testing code
+ expanding to 1, in order to specify that __VA_OPT__ is supported.
+ The actual Boost Preprocessor library for testing for emptiness in C++20 mode is called
+ BOOST_PP_CHECK_EMPTY. The macro is a variadic macro with a single variadic parameter. The
+ macro only exists if our previous macro for testing for __VA_OPT__ called BOOST_PP_VARIADIC_OPT
+ expands to 1 when invoked as BOOST_PP_VARIADIC_OPT(). If BOOST_PP_VARIADIC_OPT() expands to 0
+ the BOOST_PP_CHECK_EMPTY macro does not exist at all in this library. The input to the macro
+ can be any variadic data. If the data passed to the macro is empty, or if the data passed to
+ the macro is not empty but when the data itself is expanded it is empty, the macro returns
+ 1, otherwise it returns 0. The macro works 100% of the time and is completely reliable no matter what
+ preprocessor data is passed to it. But of course it only works when compiling at the C++20
+ level with the __VA_OPT__ construct supported by the compiler. It solves an old problem
+ that it has never been possible, prior to C++20, to provide a 100% reliable implementation
+ of a macro which tests for emptiness in C++.
+ Eventually more C++ compilers will support C++20 and the __VA_OPT__ construct and more programmers
+ will use compilers at the C++20 level. At that point the macro BOOST_PP_CHECK_EMPTY can be
+ used reliably for testing emptiness in preprocessor data in macro code by all those programmers.
+ This does not mean that designing macros with emptiness in mind needs to be done, much less
+ considered, but that the possibility of doing so with complete reliability will be there if needed
+ by the macro programmer. Along with the __VA_OPT__ construct as mandated by the C++20 standard
+ the BOOST_PP_CHECK_EMPTY adds two more tools in the arsenal of macro programming, which is a good
+ thing, while programmers who wanted to ignore any dealing with emptiness in macro code can continue to do so.
See Also
© Copyright