Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / vmd / doc / html / variadic_macro_data / vmd_specific.html
index 1382380..d9ce9c8 100644 (file)
 <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">&lt;</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">&gt;</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: