1[/ 2 (C) Copyright Edward Diener 2011-2015 3 Distributed under the Boost Software License, Version 1.0. 4 (See accompanying file LICENSE_1_0.txt or copy at 5 http://www.boost.org/LICENSE_1_0.txt). 6] 7 8[section:vmd_test_empty Emptiness] 9 10[heading Passing empty arguments] 11 12It is possible to pass an empty argument to a macro. 13The official terminology for this in the C++ standard is an argument 14"consisting of no preprocessing tokens". 15 16Let us consider a number of cases without worrying too much 17what the macro output represents. 18 19Consider these two function-like macros: 20 21 #define SMACRO() someoutput 22 #define EMACRO(x) otheroutput x 23 24The first macro takes no parameters so invoking it must always be done by 25 26 SMACRO() 27 28and passing any arguments to it would be invalid. 29 30The second macro takes a single parameter. it can be evoked as 31 32 EMACRO(somedata) 33 34but it also can be invoked as 35 36 EMACRO() 37 38In the second invocation of EMACRO we are passing an empty argument to the macro. 39Similarly for any macro having 1 or more parameters, an empty argument 40can be validly passed for any of the parameters, as in 41 42 #define MMACRO(x,y,z) x y z 43 44 MMACRO(1,,2) 45 46An empty argument is an argument even if we are passing nothing. 47 48Because an empty argument can be passed for a given parameter of 49a macro does not mean one should do so. Any given macro will specify what each 50argument to a macro should represent, and it is has normally been very rare to encounter 51a macro which specifies that an empty argument can logically be passed for a given 52argument. But from the perspective of standard C++ it is perfectly valid to 53pass an empty argument for a macro parameter. 54 55The notion of passing empty arguments can be extended to passing empty data which 56"consists of no preprocessing tokens" in slightly more complicated situations. 57It is possible to pass empty data as an argument to a variadic macro in the form of 58variadic macro data, as in 59 60 #define VMACRO(x,...) x __VA_ARGS__ 61 62invoked as 63 64 VMACRO(somedata,) 65 66Here one passes empty data as the variadic macro data and it is perfectly valid C++. 67Please notice that this different from 68 69 VMACRO(somedata) 70 71which is not valid C++, prior to C++20, since something must be passed for the variadic argument. 72In C++20 the above invocation is valid and is exactly the same as in our previous example of 73'VMACRO(somedata,)' where one passes empty data as the variadic macro data. Similarly one could 74invoke the macro as 75 76 VMACRO(somedata,vdata1,,vdata3) 77 78where one is passing variadic macro data but an element in the variadic macro data is empty. 79 80Furthermore if we are invoking a macro which expects a Boost PP data type, such as 81a tuple, we could also validly pass empty data for all or part of the data in a tuple, 82as in 83 84 #define TMACRO(x,atuple) x atuple 85 86 TMACRO(somedata,()) 87 88In this case we are passing a 1 element tuple 89where the single element itself is empty. 90 91or 92 93 TMACRO(somedata,(telem1,,telem2,teleem3)) 94 95In this case we are passing a 4 element tuple where 96the second element is empty. 97 98Again either invocation is valid C++ but it is not necessarily what the 99designed of the macro has desired, even if in both cases the macro designer 100has specified that the second parameter must be a tuple for the macro 101to work properly. 102 103[heading Returning emptiness] 104 105Similar to passing empty arguments in various ways to a macro, 106the data which a macro returns ( or 'generates' may be a better term ) 107could be empty, in various ways. Again I am not necessarily promoting 108this idea as a common occurrence of macro design but merely pointing it 109out as valid C++ preprocessing. 110 111 #define RMACRO(x,y,z) 112 113 RMACRO(data1,data2,data3) 114 115It is perfectly valid C++ to return "nothing" from a macro invocation. 116In fact a number of macros in Boost PP do that based on the preprocessor 117metaprogramming logic of the macro, and are documented as such. 118 119Similarly one could return nothing as part or all of a Boost PP 120data type or even as part of variadic macro data. 121 122 #define TRETMACRO(x,y,z) () 123 #define TRETMACRO1(x,y,z) (x,,y,,z) 124 #define VRETMACRO(x,y,z) x,,y,,z 125 126Here again we are returning something but in terms of a Boost PP 127tuple or in terms of variadic data, we have elements which are empty. 128 129[heading Emptiness in preprocessor metaprogramming] 130 131In the examples given above where "emptiness" in one form of another 132is passed as arguments to a macro or returned from a macro, the examples 133I have given were created as simplified as possible to illustrate my points. 134In actual preprocessor metaprogramming, using Boost PP, where complicated logic 135is used to generate macro output based on the arguments to a macro, it might be 136useful to allow and work with empty data if one were able to test for the fact 137that data was indeed empty. 138 139[heading Testing for empty data] 140 141Currently Boost PP has an undocumented macro for testing whether 142a parameter is empty of not, written without the use of variadic 143macros. The macro is called BOOST_PP_IS_EMPTY. The macro is by its nature flawed, 144since there is no generalized way of determining whether or not a 145parameter is empty using the C++ preprocessor prior to C++20. But the macro will 146work given input limited in various ways or if the input is actually empty. 147 148Paul Mensonides, the developer of Boost PP and the BOOST_PP_IS_EMPTY macro 149in that library, also wrote a better macro using variadic 150macros, for determining whether or not a parameter is empty or not, which 151he published on the Internet in response to a discussion about emptiness. 152This macro is also not perfect, since there is no perfect solution prior to C++20, 153but will work correctly with almost all input. I have adapted his code 154for VMD and developed my own very slightly different code. 155 156The macro is called [macroref BOOST_VMD_IS_EMPTY] and will return 1 if its input 157is empty or 0 if its input is not empty. The macro 158is a variadic macro which make take any input 159[footnote For VC++ 8 the input is not variadic data but a single parameter]. 160 161[heading Macro Flaw with a standard C++ compiler] 162 163The one situation prior to C++20 where the macro does not work properly is if 164its input resolves to a function-like macro name or a sequence of preprocessor tokens ending with 165a function-like macro name and the function-like macro takes two or more parameters. 166 167Here is a simple example: 168 169 #include <boost/vmd/is_empty.hpp> 170 171 #define FMACRO(x,y) any_output 172 173 BOOST_VMD_IS_EMPTY(FMACRO) 174 BOOST_VMD_IS_EMPTY(some_input FMACRO) 175 176In the first case the name of a function-like macro is being passed to 177BOOST_VMD_IS_EMPTY while in the second case a sequence of preprocessing tokens is being 178passed to BOOST_VMD_IS_EMPTY ending with the name of a function-like macro. 179The function-like macro also has two ( or more ) parameters. In both the 180cases above a compiler error will result from the use of BOOST_VMD_IS_EMPTY. 181 182Please note that these two problematical cases are not the same as passing 183an invocation of a function-like macro name to BOOST_VMD_IS_EMPTY, as in 184 185 #include <boost/vmd/is_empty.hpp> 186 187 BOOST_VMD_IS_EMPTY(FMACRO(arg1,arg2)) 188 BOOST_VMD_IS_EMPTY(someinput FMACRO(arg1,arg2)) 189 190which always works correctly, unless of course a particular function-like macro 191invocation resolves to either of our two previous situations. 192 193Another situation where the macro may not work properly is if the previously mentioned 194function-like macro takes a single parameter but creates an error when the argument 195passed is empty. An example of this would be: 196 197 #define FMACRO(x) BOOST_PP_CAT(+,x C); 198 199When nothing is passed to FMACRO undefined behavior will occur since attempting to concatenate 200'+' to ' C' is UB in C++ preprocessor terms. 201 202So for a standard conforming compiler, prior to C++20, we have essentially two corner cases where 203the BOOST_VMD_IS_EMPTY does not work and, when it does not work it, produces a 204compiler error rather than an incorrect result. Essentially what is desired for maximum 205safety is that we never pass input ending with the name of a function-like macro name when 206testing for emptiness. 207 208[heading Macro Flaw with Visual C++] 209 210The VC++ preprocessor is not a standard C++ conforming preprocessor in at least two 211relevant situations to our discussion of emptiness. These situations combine to create 212a single corner case which causes the BOOST_VMD_IS_EMPTY macro to not work properly 213using VC++ when the input resolves to a function-like macro name. 214 215The first situation, related to our discussion of emptiness, where the VC++ preprocessor 216is not a standard C++ conforming preprocessor is that if a macro taking 'n' number of parameters is invoked 217with 0 to 'n-1' parameters, the compiler does not give an error, but only a warning. 218 219 #define FMACRO(x,y) x + y 220 221 FMACRO(1) 222 223should give a compiler error, as it does when using a C++ standard-conforming 224compiler, but when invoked using VC++ it only gives a warning 225and VC++ continues macro substitution with 'y' as a placemarker preprocessing token. 226This non-standard conforming action actually eliminates the case where BOOST_VMD_IS_EMPTY 227does not work properly with a standard C++ conforming compiler. But of course it has the 228potential of producing incorrect output in other macro processing situations unrelated 229to the BOOST_VMD_IS_EMPTY invocation, where a compiler error should occur. 230 231A second general situation, related to our discussion of emptiness, where the VC++ preprocessor 232is not a standard C++ conforming preprocessor is that the expansion of a macro works incorrectly 233when the expanded macro is a function-like macro name followed by a function-like macro invocation, 234in which case the macro re-expansion is erroneously done more than once. This latter case can be 235seen by this example: 236 237 #define FMACRO1(parameter) FMACRO3 parameter() 238 #define FMACRO2() () 239 #define FMACRO3() 1 240 241 FMACRO1(FMACRO2) 242 243 should expand to: 244 245 FMACRO3() 246 247 but in VC++ it expands to: 248 249 1 250 251where after initially expanding the macro to: 252 253 FMACRO3 FMACRO2() 254 255VC++ erroneously rescans the sequence of preprocessing tokens more than once rather than 256rescan just one more time for more macro names. 257 258What these two particular preprocessor flaws in the VC++ compiler mean is that although 259BOOST_VMD_IS_EMPTY does not fail with a compiler error in the same case as with 260a standard C++ conforming compiler given previously, it fails by giving 261the wrong result in another situation. 262 263The failing situation is: 264 265when the input to BOOST_VMD_IS_EMPTY resolves to only a function-like macro 266name, and the function-like macro, when passed a single empty argument, expands to 267a Boost PP tuple, BOOST_VMD_IS_EMPTY will erroneously return 1 when using the Visual C++ 268compiler rather than either give a preprocessing error or return 0. 269 270Here is an example of the failure: 271 272 #include <boost/vmd/is_empty.hpp> 273 274 #define FMACRO4() ( any_number_of_tuple_elements ) 275 #define FMACRO5(param) ( any_number_of_tuple_elements ) 276 #define FMACRO6(param1,param2) ( any_number_of_tuple_elements ) 277 278 BOOST_VMD_IS_EMPTY(FMACRO4) // erroneously returns 1, instead of 0 279 BOOST_VMD_IS_EMPTY(FMACRO5) // erroneously returns 1, instead of 0 280 BOOST_VMD_IS_EMPTY(FMACRO6) // erroneously returns 1, instead of generating a preprocessing error 281 282As with a standard C++ conforming compiler prior to C++20, we have a rare corner case where 283the BOOST_VMD_IS_EMPTY will not work properly, but unfortunately in this very 284similar but even rarer corner case with VC++, we will silently get an incorrect result 285rather than a compiler error. 286 287I want to reiterate that for all compilers prior to C++20 there is no perfect solution 288in C++ to the detection of emptiness even for a C++ compiler whose preprocessor is completely 289conformant, which VC++ obviously is not. 290 291[heading Testing emptiness in C++20 mode] 292 293A few compilers can currently operate in C++20 mode, by which I mean that you 294can pass a compiler flag when compiling with such a compiler which enforces the 295upcoming C++20 standard. One of the features of the C++20 standard is the 296addition of a preprocessor construct called __VA_OPT__. Because of the 297specification of how the __VA_OPT__ construct works in C++20, it is now possible 298to have the BOOST_VMD_IS_EMPTY macro work perfectly to test for emptiness without 299any of the flaws that exist in the macro for levels of the C++ standard before 300C++20. But the macro will only do a 100% reliable test for emptiness when the 301compiler is compiling in C++20 mode. For all levels of the C++ standard before 302C++20, such as C++98, C++03, C++11, C++14, and C++17, the testing for emptiness 303has the corner cases which prevent it from wroking perfectly which have already 304been discussed. 305 306Furthermore in C++20 mode it is possible that a compiler still does not yet 307support the __VA_OPT__ construct, even though it is part of the C++20 standard. 308Luckily it is possible to test whether or not a compiler supports the __VA_OPT__ 309construct in C++20 mode, and the macro implementation of BOOST_VMD_IS_EMPTY 310does that before using the construct to provide a perfectly reliable 311implementation for testing emptiness. 312 313The result of all this is that when a compiler is compiling source using 314the C++20 standard, and supports the C++20 __VA_OPT__ preprocessor construct, 315the implementation provides a completely reliable way of testing for emptiness 316using the BOOST_VMD_IS_EMPTY macro. Otherwise the BOOST_VMD_IS_EMPTY macro 317has the corner cases previously discussed which make the macro less than 318100% reliable in testing for emptiness. The good news of course is that 319more compilers will be implementaing the C++20 standard and more C++ 320programmers will be using the C++20 standard to compile their code. 321 322The programmer may know whether the compiler is being used in C++20 mode 323from the command line parameters he passes to the compiler, and the programmer 324may know whether the compiler in C++20 mode supports the __VA_OPT__ construct 325of C++20 from the compiler's documentation. But from the preprocessor programming 326perspective it would be good to find out using a macro whether or not C++20 mode 327with the __VA_OPT__ construct is being used so that the BOOST_VMD_IS_EMPTY 328macro can be considered completely reliable in testing for emptiness. Such a macro 329does already exist in the Boost Preprocessor library, and it is called BOOST_PP_VARIADIC_HAS_OPT. 330You can read the documentation for this macro in the Boost Preprocessor library 331documentation, but I will give a quick rundown of how this works here. The macro 332is a function-like macro taking no parameters and returns 1 if the compiler 333is in C++20 mode and __VA_OPT__ is supported, otherwise returns 0. The header 334file needed to invoke the macro as BOOST_PP_VARIADIC_HAS_OPT() is included as: 335 336 #include <boost/preprocessor/variadic/has_opt.hpp> 337 338The programmer does not have to be compiling in C++20 mode to invoke the 339BOOST_PP_VARIADIC_HAS_OPT macro. When the programmer is not in C++20 mode invoking 340the macro always returns 0. When the programmer is in C++20 mode invoking 341the macro returns 1 when the __VA_OPT__ construct is supported and returns 0 342when the __VA_OPT__ construct is not supported. It does this latter step through 343clever preprocessor programming. 344 345[heading Macro Flaw conclusion] 346 347With all of the above mentioned, the cases where BOOST_VMD_IS_EMPTY will work 348incorrectly are very small, even with the erroneous VC++ preprocessor, 349and I consider the macro worthwhile to use since it works correctly with the vast 350majority of possible preprocessor input, and always works correctly in C++20 351mode with __VA_OPT__ preprocessor support. 352 353The case where it will not work, with both a C++ standard conforming preprocessor or 354with Visual C++, occurs when the name of a function-like macro is part of the input 355to BOOST_VMD_IS_EMPTY. Obviously the macro should be used by the preprocessor 356metaprogrammer when the possible input to it is constrained to eliminate the erroneous 357case. 358 359Since emptiness can correctly be tested for in nearly every situation, the 360BOOST_VMD_IS_EMPTY macro can be used internally when the preprocessor metaprogrammer wants to return data 361from a macro and all or part of that data could be empty. 362 363Therefore I believe the BOOST_VMD_IS_EMPTY macro is quite useful, despite the corner case flaws 364which makes it imperfect. Consequently I believe that the preprocessor metaprogrammer 365can use the concept of empty preprocessor data in the design of his own macros. 366 367[heading Using the macro] 368 369The macro BOOST_VMD_IS_EMPTY is used internally throughout VMD and macro programmers 370may find this macro useful in their own programming efforts despite the slight flaw 371in the way that it works in pre C++20 mode. 372 373You can use the general header file: 374 375 #include <boost/vmd/vmd.hpp> 376 377or you can use the individual header file: 378 379 #include <boost/vmd/is_empty.hpp> 380 381for the BOOST_VMD_IS_EMPTY macro. 382 383[endsect] 384