<pre class="programlisting"><span class="identifier">VMACRO</span><span class="special">(</span><span class="identifier">somedata</span><span class="special">)</span>
</pre>
<p>
- which is not valid C++ since something must be passed for the variadic argument.
- Similar one could invoke the macro as
+ which is not valid C++, prior to C++20, since something must be passed for
+ the variadic argument. In C++20 the above invocation is valid and is exactly
+ the same as in our previous example of 'VMACRO(somedata,)' where one passes
+ empty data as the variadic macro data. Similarly one could invoke the macro
+ as
</p>
<pre class="programlisting"><span class="identifier">VMACRO</span><span class="special">(</span><span class="identifier">somedata</span><span class="special">,</span><span class="identifier">vdata1</span><span class="special">,,</span><span class="identifier">vdata3</span><span class="special">)</span>
</pre>
is empty of not, written without the use of variadic macros. The macro is
called BOOST_PP_IS_EMPTY. The macro is by its nature flawed, since there
is no generalized way of determining whether or not a parameter is empty
- using the C++ preprocessor. But the macro will work given input limited in
- various ways or if the input is actually empty.
+ using the C++ preprocessor prior to C++20. But the macro will work given
+ input limited in various ways or if the input is actually empty.
</p>
<p>
Paul Mensonides, the developer of Boost PP and the BOOST_PP_IS_EMPTY macro
in that library, also wrote a better macro using variadic macros, for determining
whether or not a parameter is empty or not, which he published on the Internet
in response to a discussion about emptiness. This macro is also not perfect,
- since there is no perfect solution, but will work correctly with almost all
- input. I have adapted his code for the VMD and developed my own very slightly
- different code.
+ since there is no perfect solution prior to C++20, but will work correctly
+ with almost all input. I have adapted his code for VMD and developed my own
+ very slightly different code.
</p>
<p>
The macro is called <code class="computeroutput"><a class="link" href="../BOOST_VMD_IS_EMPTY.html" title="Macro BOOST_VMD_IS_EMPTY">BOOST_VMD_IS_EMPTY</a></code>
Flaw with a standard C++ compiler</a>
</h5>
<p>
- The one situation where the macro always does not work properly is if its
- input resolves to a function-like macro name or a sequence of preprocessor
+ The one situation prior to C++20 where the macro does not work properly is
+ if its input resolves to a function-like macro name or a sequence of preprocessor
tokens ending with a function-like macro name and the function-like macro
takes two or more parameters.
</p>
to concatenate '+' to ' C' is UB in C++ preprocessor terms.
</p>
<p>
- So for a standard conforming compiler we have essentially a single corner
- case where the BOOST_VMD_IS_EMPTY does not work and, when it does not work
- it, produces a compiler error rather than an incorrect result. Essentially
- what is desired for maximum safety is that we never pass input ending with
- the name of a function-like macro name when testing for emptiness.
+ So for a standard conforming compiler, prior to C++20, we have essentially
+ two corner cases where the BOOST_VMD_IS_EMPTY does not work and, when it
+ does not work it, produces a compiler error rather than an incorrect result.
+ Essentially what is desired for maximum safety is that we never pass input
+ ending with the name of a function-like macro name when testing for emptiness.
</p>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_test_empty.h5"></a>
<span class="identifier">BOOST_VMD_IS_EMPTY</span><span class="special">(</span><span class="identifier">FMACRO6</span><span class="special">)</span> <span class="comment">// erroneously returns 1, instead of generating a preprocessing error</span>
</pre>
<p>
- As with a standard C++ conforming compiler, we have a rare corner case where
- the BOOST_VMD_IS_EMPTY will not work properly, but unfortunately in this
- very similar but even rarer corner case with VC++, we will silently get an
- incorrect result rather than a compiler error.
+ As with a standard C++ conforming compiler prior to C++20, we have a rare
+ corner case where the BOOST_VMD_IS_EMPTY will not work properly, but unfortunately
+ in this very similar but even rarer corner case with VC++, we will silently
+ get an incorrect result rather than a compiler error.
</p>
<p>
- I want to reiterate that there is no perfect solution in C++ to the detection
- of emptiness even for a C++ compiler whose preprocessor is completely conformant,
- which VC++ obviously is not.
+ I want to reiterate that for all compilers prior to C++20 there is no perfect
+ solution in C++ to the detection of emptiness even for a C++ compiler whose
+ preprocessor is completely conformant, which VC++ obviously is not.
</p>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_test_empty.h6"></a>
+ <span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_test_empty.testing_emptiness_in_c_20_mode"></a></span><a class="link" href="vmd_specific.html#variadic_macro_data.vmd_specific.vmd_test_empty.testing_emptiness_in_c_20_mode">Testing
+ emptiness in C++20 mode</a>
+ </h5>
+<p>
+ A few compilers can currently operate in C++20 mode, by which I mean that
+ you can pass a compiler flag when compiling with such a compiler which enforces
+ the upcoming C++20 standard. One of the features of the C++20 standard is
+ the addition of a preprocessor construct called __VA_OPT__. Because of the
+ specification of how the __VA_OPT__ construct works in C++20, it is now possible
+ to have the BOOST_VMD_IS_EMPTY macro work perfectly to test for emptiness
+ without any of the flaws that exist in the macro for levels of the C++ standard
+ before C++20. But the macro will only do a 100% reliable test for emptiness
+ when the compiler is compiling in C++20 mode. For all levels of the C++ standard
+ before C++20, such as C++98, C++03, C++11, C++14, and C++17, the testing
+ for emptiness has the corner cases which prevent it from wroking perfectly
+ which have already been discussed.
+ </p>
+<p>
+ Furthermore in C++20 mode it is possible that a compiler still does not yet
+ support the __VA_OPT__ construct, even though it is part of the C++20 standard.
+ Luckily it is possible to test whether or not a compiler supports the __VA_OPT__
+ construct in C++20 mode, and the macro implementation of BOOST_VMD_IS_EMPTY
+ does that before using the construct to provide a perfectly reliable implementation
+ for testing emptiness.
+ </p>
+<p>
+ The result of all this is that when a compiler is compiling source using
+ the C++20 standard, and supports the C++20 __VA_OPT__ preprocessor construct,
+ the implementation provides a completely reliable way of testing for emptiness
+ using the BOOST_VMD_IS_EMPTY macro. Otherwise the BOOST_VMD_IS_EMPTY macro
+ has the corner cases previously discussed which make the macro less than
+ 100% reliable in testing for emptiness. The good news of course is that more
+ compilers will be implementaing the C++20 standard and more C++ programmers
+ will be using the C++20 standard to compile their code.
+ </p>
+<p>
+ The programmer may know whether the compiler is being used in C++20 mode
+ from the command line parameters he passes to the compiler, and the programmer
+ may know whether the compiler in C++20 mode supports the __VA_OPT__ construct
+ of C++20 from the compiler's documentation. But from the preprocessor programming
+ perspective it would be good to find out using a macro whether or not C++20
+ mode with the __VA_OPT__ construct is being used so that the BOOST_VMD_IS_EMPTY
+ macro can be considered completely reliable in testing for emptiness. Such
+ a macro does already exist in the Boost Preprocessor library, and it is called
+ BOOST_PP_VARIADIC_HAS_OPT. You can read the documentation for this macro
+ in the Boost Preprocessor library documentation, but I will give a quick
+ rundown of how this works here. The macro is a function-like macro taking
+ no parameters and returns 1 if the compiler is in C++20 mode and __VA_OPT__
+ is supported, otherwise returns 0. The header file needed to invoke the macro
+ as BOOST_PP_VARIADIC_HAS_OPT() is included as:
+ </p>
+<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">variadic</span><span class="special">/</span><span class="identifier">has_opt</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+ The programmer does not have to be compiling in C++20 mode to invoke the
+ BOOST_PP_VARIADIC_HAS_OPT macro. When the programmer is not in C++20 mode
+ invoking the macro always returns 0. When the programmer is in C++20 mode
+ invoking the macro returns 1 when the __VA_OPT__ construct is supported and
+ returns 0 when the __VA_OPT__ construct is not supported. It does this latter
+ step through clever preprocessor programming.
+ </p>
+<h5>
+<a name="variadic_macro_data.vmd_specific.vmd_test_empty.h7"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_test_empty.macro_flaw_conclusion"></a></span><a class="link" href="vmd_specific.html#variadic_macro_data.vmd_specific.vmd_test_empty.macro_flaw_conclusion">Macro
Flaw conclusion</a>
</h5>
<p>
- With all of the above mentioned, the case(s) where BOOST_VMD_IS_EMPTY will
+ With all of the above mentioned, the cases where BOOST_VMD_IS_EMPTY will
work incorrectly are very small, even with the erroneous VC++ preprocessor,
and I consider the macro worthwhile to use since it works correctly with
- the vast majority of possible preprocessor input.
+ the vast majority of possible preprocessor input, and always works correctly
+ in C++20 mode with __VA_OPT__ preprocessor support.
</p>
<p>
The case where it will not work, with both a C++ standard conforming preprocessor
</p>
<p>
Therefore I believe the BOOST_VMD_IS_EMPTY macro is quite useful, despite
- the corner case flaw which makes it imperfect. Consequently I believe that
+ the corner case flaws which makes it imperfect. Consequently I believe that
the preprocessor metaprogrammer can use the concept of empty preprocessor
data in the design of his own macros.
</p>
<h5>
-<a name="variadic_macro_data.vmd_specific.vmd_test_empty.h7"></a>
+<a name="variadic_macro_data.vmd_specific.vmd_test_empty.h8"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_test_empty.using_the_macro"></a></span><a class="link" href="vmd_specific.html#variadic_macro_data.vmd_specific.vmd_test_empty.using_the_macro">Using
the macro</a>
</h5>
<p>
The macro BOOST_VMD_IS_EMPTY is used internally throughout VMD and macro
programmers may find this macro useful in their own programming efforts despite
- the slight flaw in the way that it works.
+ the slight flaw in the way that it works in pre C++20 mode.
</p>
<p>
You can use the general header file: