123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <meta content="text/html; charset=windows-1252"
- http-equiv="content-type">
- <title>emptiness.html</title>
- <link rel="stylesheet" type="text/css" href="../styles.css">
- <style>
- u { font-weight: normal; text-decoration: none; }
- </style>
- </head>
- <body>
- <h4>Passing nothing</h4>
- <div> 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. </div>
- <div class="code">
- <pre> #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
- SOME_MACRO(a,) // Legal, second argument is empty
- SOME_MACRO(,b) // Legal, first argument is empty
- SOME_MACRO(a) // Preprocessor error, passing the wrong number of arguments
-
- SOME_VARIADIC_MACRO(a,b,c,d) // Normal
- SOME_VARIADIC_MACRO(a,) // Legal, variadic argument is empty
- SOME_VARIADIC_MACRO(,b,c,d) // Legal, first argument is empty
- SOME_VARIADIC_MACRO(a) /* Preprocessor error in standard below C++20 level,
- but in C++20 exactly equivalent to SOME_VARIADIC_MACRO(a,) */</pre>
- </div>
- <h4>Expanding to nothing</h4>
- <div> 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. </div>
- <div class="code">
- <pre> #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</pre>
- </div>
- <h4>Emptiness defined</h4>
- <div> 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.<br>
- <br>
- 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.<br>
- <br>
- 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. </div>
- <h4>A C++20 solution for testing for emptiness</h4>
- <div> 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. <br>
- <br>
- 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.<br>
- <br>
- 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.<br>
- <br>
- 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.<br>
- <br>
- 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++.<br>
- <br>
- 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 <b>not</b> 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.<br>
- <br>
- 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. </div>
- <b>See</b> <b>Also</b><br>
- <ul>
- <li><a href="../ref/variadic_has_opt.html">BOOST_PP_VARIADIC_HAS_OPT</a></li>
- <li><a href="../ref/check_empty.html">BOOST_PP_CHECK_EMPTY</a></li>
- <li><a href="../ref/va_opt.html">BOOST_PP_VA_OPT</a><br>
- </li>
- </ul>
- <hr size="1">
- <div style="margin-left: 0px;"> <i>© Copyright Edward Diener 2019</i>
- </div>
- <div style="margin-left: 0px;">
- <p><small>Distributed under the Boost Software License, Version
- 1.0. (See accompanying file <a
- href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
- copy at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</small></p>
- </div>
- </body>
- </html>
|