diff --git a/doc/topics/emptiness.html b/doc/topics/emptiness.html index b86c7c1..ce346c8 100644 --- a/doc/topics/emptiness.html +++ b/doc/topics/emptiness.html @@ -1,21 +1,22 @@ + - + emptiness.html - +

Passing nothing

-
- Although rarely desirable it has always been legal in C++ to pass nothing, aka no preprocessor tokens, - as an argument when invoking a macro, whether the equivalent parameter be a regular parameter or a variadic one. -
-
-
-      #define SOME_MACRO(Parameter1,Parameter2) macro expansion using Parameter1 and Parameter2
+    
Although rarely desirable it has always been legal in C++ to + pass nothing, aka no preprocessor tokens, as an argument when + invoking a macro, whether the equivalent parameter be a regular + parameter or a variadic one.
+
+
      #define SOME_MACRO(Parameter1,Parameter2) macro expansion using Parameter1 and Parameter2
       #define SOME_VARIADIC_MACRO(Parameter1,...) macro expansion using Parameter1 and __VA_ARGS__
       
       SOME_MACRO(a,b) // Normal
@@ -30,17 +31,17 @@
                                       but in C++20 exactly equivalent to SOME_VARIADIC_MACRO(a,) */

Expanding to nothing

-
- Given certain arguments a macro might expand to nothing, aka no preprocessor tokens. This may - happen more than in 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 that macro's expansion is used as an argument to another macro because we would again have - a macro where we are passing nothing as an argument. -
-
-
-      #define ANOTHER_MACRO(Parameter1,Parameter2) /* expands to nothing when Parameter1 and Parameter2
+    
Given certain arguments a macro might expand to nothing, aka + no preprocessor tokens. This may happen more than in 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 + that macro's expansion is used as an argument to another macro + because we would again have a macro where we are passing nothing + as an argument.
+
+
      #define ANOTHER_MACRO(Parameter1,Parameter2) /* expands to nothing when Parameter1 and Parameter2
                                                       are numbers, otherwise expands to some preprocessing
                                                       token, such as '1' */
       
@@ -50,103 +51,161 @@
       SOME_MACRO(ANOTHER_MACRO(1,2),z)          // Legal, first argument is empty as ANOTHER_MACRO Expands to nothing

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. -
+
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_HAS_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_HAS_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_HAS_OPT - expands to 1 when invoked as BOOST_PP_VARIADIC_HAS_OPT(). If BOOST_PP_VARIADIC_HAS_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. -
+
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__, as in '__VA_OPT__ ( prepocessing tokens )' specified + in the replacement list of a variadic macro.
+
+ The way that the __VA_OPT__ constructs works is that if the + variadic arguments to the variadic macro are empty or expand to + emptiness then the __VA_OPT__ construct and its enclosed + preprocessing token data expands to nothing, or in C++ terms "a + single placemarker preprocessing token". Otherwise the __VA_OPT__ + construct expands to its enclosed preprocessing tokens. A further, + possibly unintended, 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_HAS_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_HAS_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_HAS_OPT, expands to 1 when invoked as + BOOST_PP_VARIADIC_HAS_OPT(). If BOOST_PP_VARIADIC_HAS_OPT() + expands to 0 the BOOST_PP_CHECK_EMPTY macro does not exist at all + in this library. The input to the BOOST_PP_CHECK_EMPTY 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++.
+
+ Along with the valuable BOOST_PP_CHECK_EMPTY macro the Boost + Preprocessor library has also added a more flexible, if slightly + verbose, alternative to the __VA_OPT__ construct, which works by + using the ability of BOOST_PP_CHECK_EMPTY to reliably test for + emptiness. This macro is called BOOST_PP_VA_OPT and allows the + programmer to specify preprocessing tokens for expansion both when + the variadic data is not empty and when the variadic data + is empty. This improves on the __VA_OPT__ construct's ability to + specify preprocessing tokens for expansion only when the variadic + data is not empty. Like BOOST_PP_CHECK_EMPTY, which it uses, the + BOOST_PP_VA_OPT macro only exists when BOOST_PP_VARIADIC_HAS_OPT() + expands to 1. You can read further about how this macro works as + an alternative to the C++20 __VA_OPT__ construct in the + documentation for the macro itself.
+
+ 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. The BOOST_PP_VA_OPT macro + serves as a useful example of such use. 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 and BOOST_PP_VA_OPT macros + add three 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 - Edward Diener - 2019
-
-

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)

+
+
© Copyright Edward Diener 2019 +
+
+

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 +