Merge branch 'develop'

This commit is contained in:
Edward Diener
2019-10-09 12:48:38 -04:00
12 changed files with 359 additions and 0 deletions

View File

@ -80,6 +80,7 @@
<li><a href="headers/facilities.html">facilities.hpp</a></li>
<li>facilities/</li>
<li class="ps"><a href="headers/facilities/apply.html">apply.hpp</a></li>
<li class="ps"><a href="headers/facilities/check_empty.html">check_empty.hpp</a></li>
<li class="ps"><a href="headers/facilities/empty.html">empty.hpp</a></li>
<li class="ps"><a href="headers/facilities/expand.html">expand.hpp</a></li>
<li class="ps"><a href="headers/facilities/identity.html">identity.hpp</a></li>

View File

@ -0,0 +1,29 @@
<html>
<head>
<title>facilities/check_empty.hpp</title>
<link rel="stylesheet" type="text/css" href="../../styles.css">
</head>
<body>
<div style="margin-left: 0px;">
The <b>facilities/check_empty.hpp</b> header defines a variadic macro for the C++20 level that checks if its data is empty or not.
</div>
<h4>Usage</h4>
<div class="code">
#include <b>&lt;boost/preprocessor/facilities/check_empty.hpp&gt;</b>
</div>
<h4>Contents</h4>
<ul>
<li><a href="../../ref/check_empty.html">BOOST_PP_CHECK_EMPTY</a></li>
</ul>
<hr size="1">
<div style="margin-left: 0px;">
<i></i><i><EFBFBD> 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>

View File

@ -45,6 +45,7 @@
<li><a href="ref/bool.html">BOOL</a></li>
<!-- C -->
<li><a href="ref/cat.html">CAT</a></li>
<li><a href="ref/check_empty.html">CHECK_EMPTY</a></li>
<li><a href="ref/comma.html">COMMA</a></li>
<li><a href="ref/comma_if.html">COMMA_IF</a></li>
<li><a href="ref/compl.html">COMPL</a></li>

68
doc/ref/check_empty.html Normal file
View File

@ -0,0 +1,68 @@
<html>
<head>
<title>BOOST_PP_CHECK_EMPTY</title>
<link rel="stylesheet" type="text/css" href="../styles.css">
</head>
<body>
<div style="margin-left: 0px;"> The <b>BOOST_PP_CHECK_EMPTY</b> variadic macro
checks to see if its variadic input is empty or not. It expands to 1 if its input
is empty and expands to 0 if its input is not empty. The macro only exists when
the compilation is at the C++20 level and the __VA_OPT__ construct is supported.</div>
<h4>Usage</h4>
<div class="code"> <b>BOOST_PP_CHECK_EMPTY</b>(<i>...</i>) <a href="../topics/variadic_macros.html#VNotation" target="_self"><sup>(v)</sup></a><br>
</div>
<h4>Arguments</h4>
<dl>
<dt>...<br>
</dt>
<dd> The <i>variadic data</i> to be checked for emptiness. </dd>
</dl>
<h4>Remarks</h4>
<div>
When the macro invocation BOOST_PP_VARIADIC_OPT() expands to 1, then this
macro exists and can be invoked, otherwise this macro does not exist
and attempting to invoke it will lead to a preprocessor error that the macro
can not be found. Because of this condition the header file for including
this macro includes the header file for the BOOST_PP_VARIADIC_OPT macro.<br>
It is possible to pass data to this macro which expands to nothing, in which
case this macro will expand to 1 just as if nothing has been passed.
</div>
<h4>See Also</h4>
<ul>
<li><a href="variadic_opt.html">BOOST_PP_VARIADIC_OPT</a></li>
</ul>
<h4>Requirements</h4>
<div> <b>Header:</b> &nbsp;<a href="../headers/facilities/check_empty.html">&lt;boost/preprocessor/facilities/check_empty.hpp&gt;</a>
</div>
<h4>Sample Code</h4>
<div>
<pre>
#include &lt;<a href="../headers/facilities/check_empty.html">boost/preprocessor/facilities/check_empty.hpp</a>&gt;
# if <a href="variadic_opt.html">BOOST_PP_VARIADIC_OPT</a>()
#define DATA
#define OBJECT OBJECT2
#define OBJECT2
#define FUNC(x) FUNC2(x)
#define FUNC2(x)
#define FUNC_GEN(x,y) (1,2,3)
<a href="check_empty.html">BOOST_PP_CHECK_EMPTY</a>(DATA) // expands to 1
<a href="check_empty.html">BOOST_PP_CHECK_EMPTY</a>(OBJECT) // expands to 1
<a href="check_empty.html">BOOST_PP_CHECK_EMPTY</a>(FUNC(1)) // expands to 1
<a href="check_empty.html">BOOST_PP_CHECK_EMPTY</a>(FUNC) // expands to 0
<a href="check_empty.html">BOOST_PP_CHECK_EMPTY</a>(FUNC_GEN) // expands to 0
#endif
</pre>
</div>
<hr size="1">
<div style="margin-left: 0px;"> <i></i><i><EFBFBD> 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>

View File

@ -16,6 +16,19 @@ Expands to 1 if the __VA_OPT__ construct is supported, otherwise expands to 0.
<dt>None<br>
</dt>
</dl>
<h4>Remarks</h4>
<div>
This macro only returns 1 if the compiler is compiling at its own C++20 level and
__VA_OPT__ is supported. It is possible for a compiler to support the __VA_OPT__
construct when not compiling at its own C++20 level, but this macro will return
0 in that case even if __VA_OPT__ is normally supported for that level. The reason
for this is that such a compiler may have a compiler switch, enforcing a strict
adherence to a particular C++ standard level, which gives a warning or an error
if __VA_OPT__ is specified below the C++20 level, and the preprocessor library
wants to avoid that happening. Therefore the macro will only test to see whether
or not __VA_OPT__ is supported at the C++20 level, while otherwise always returning
0 for all lesser C++ standard levels.
</div>
<h4>Requirements</h4>
<div> <b>Header:</b> &nbsp;<a href="../headers/variadic/opt.html">&lt;boost/preprocessor/variadic/opt.hpp&gt;</a>
</div>

View File

@ -15,6 +15,7 @@
<li><a href="topics/file_iteration.html">file iteration</a></li>
<li><a href="topics/evaluated_slots.html">evaluated slots</a></li>
<li><a href="topics/variadic_macros.html">variadic macros</a></li>
<li><a href="topics/emptiness.html">emptiness</a></li>
</ul>
<!--
<EFBFBD> Copyright Housemarque Oy 2002

152
doc/topics/emptiness.html Normal file
View File

@ -0,0 +1,152 @@
<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 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 a macro's expansion is used as an argument to another macro, although
again it is perfectly legal C++.
</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__. 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.<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_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_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_OPT
expands to 1 when invoked as BOOST_PP_VARIADIC_OPT(). If BOOST_PP_VARIADIC_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++.<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.
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.
</div>
<b>See</b> <b>Also</b><br>
<ul>
<li><a href="../ref/variadic_opt.html">BOOST_PP_VARIADIC_OPT</a></li>
<li><a href="../ref/check_empty.html">BOOST_PP_CHECK_EMPTY</a></li>
</ul>
<hr size="1">
<div style="margin-left: 0px;"> <i><EFBFBD> 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>

View File

@ -14,6 +14,7 @@
# define BOOST_PREPROCESSOR_FACILITIES_HPP
#
# include <boost/preprocessor/facilities/apply.hpp>
# include <boost/preprocessor/facilities/check_empty.hpp>
# include <boost/preprocessor/facilities/empty.hpp>
# include <boost/preprocessor/facilities/expand.hpp>
# include <boost/preprocessor/facilities/identity.hpp>

View File

@ -0,0 +1,19 @@
# /* **************************************************************************
# * *
# * (C) Copyright Edward Diener 2019.
# * Distributed under the Boost Software License, Version 1.0. (See
# * accompanying file LICENSE_1_0.txt or copy at
# * http://www.boost.org/LICENSE_1_0.txt)
# * *
# ************************************************************************** */
#
# /* See http://www.boost.org for most recent version. */
#
# ifndef BOOST_PREPROCESSOR_FACILITIES_CHECK_EMPTY_HPP
# define BOOST_PREPROCESSOR_FACILITIES_CHECK_EMPTY_HPP
# include <boost/preprocessor/variadic/opt.hpp>
# if BOOST_PP_VARIADIC_OPT()
# include <boost/preprocessor/facilities/is_empty_variadic.hpp>
# define BOOST_PP_CHECK_EMPTY(...) BOOST_PP_IS_EMPTY_OPT(__VA_ARGS__)
# endif /* BOOST_PP_VARIADIC_OPT() */
# endif /* BOOST_PREPROCESSOR_FACILITIES_CHECK_EMPTY_HPP */

View File

@ -211,6 +211,7 @@ alias preprocessor_isempty : :
alias preprocessor_isempty
:
[ compile isempty.cpp ]
[ compile checkempty.cpp ]
[ compile-fail isempty_variadic_standard_failure.cpp : <define>BOOST_PP_VARIADICS=1 ]
[ compile-fail isempty_variadic_standard_failure2.cpp : <define>BOOST_PP_VARIADICS=1 ]
;

12
test/checkempty.cpp Normal file
View File

@ -0,0 +1,12 @@
# /* **************************************************************************
# * *
# * (C) Copyright Edward Diener 2019.
# * Distributed under the Boost Software License, Version 1.0. (See
# * accompanying file LICENSE_1_0.txt or copy at
# * http://www.boost.org/LICENSE_1_0.txt)
# * *
# ************************************************************************** */
#
# /* See http://www.boost.org for most recent version. */
#
# include <libs/preprocessor/test/checkempty.cxx>

61
test/checkempty.cxx Normal file
View File

@ -0,0 +1,61 @@
# /* **************************************************************************
# * *
# * (C) Copyright Edward Diener 2019.
# * Distributed under the Boost Software License, Version 1.0. (See
# * accompanying file LICENSE_1_0.txt or copy at
# * http://www.boost.org/LICENSE_1_0.txt)
# * *
# ************************************************************************** */
#
# /* See http://www.boost.org for most recent version. */
#
# include <libs/preprocessor/test/test.h>
# include <boost/preprocessor/facilities/check_empty.hpp>
# if BOOST_PP_VARIADIC_OPT()
# include <boost/preprocessor/facilities/empty.hpp>
#define DATA
#define OBJECT OBJECT2
#define OBJECT2
#define FUNC(x) FUNC2(x)
#define FUNC2(x)
#define FUNC_GEN() ()
#define FUNC_GEN2(x) ()
#define FUNC_GEN3() (&)
#define FUNC_GEN4(x) (y)
#define FUNC_GEN5() (y,z)
#define FUNC_GEN6() anything
#define FUNC_GEN7(x) anything
#define FUNC_GEN8(x,y) (1,2,3)
#define FUNC_GEN9(x,y,z) anything
#define FUNC_GEN10(x) (y) data
#define NAME &name
#define ATUPLE (atuple)
#define ATUPLE_PLUS (atuple) data
BEGIN BOOST_PP_CHECK_EMPTY(FUNC_GEN) == 0 END
BEGIN BOOST_PP_CHECK_EMPTY(FUNC_GEN2) == 0 END
BEGIN BOOST_PP_CHECK_EMPTY(FUNC_GEN3) == 0 END
BEGIN BOOST_PP_CHECK_EMPTY(FUNC_GEN4) == 0 END
BEGIN BOOST_PP_CHECK_EMPTY(FUNC_GEN5) == 0 END
BEGIN BOOST_PP_CHECK_EMPTY(FUNC_GEN8) == 0 END
BEGIN BOOST_PP_CHECK_EMPTY(FUNC_GEN9) == 0 END
BEGIN BOOST_PP_CHECK_EMPTY(FUNC_GEN10) == 0 END
BEGIN BOOST_PP_CHECK_EMPTY(BOOST_PP_EMPTY()) == 1 END
BEGIN BOOST_PP_CHECK_EMPTY(DATA BOOST_PP_EMPTY()) == 1 END
BEGIN BOOST_PP_CHECK_EMPTY(x BOOST_PP_EMPTY()) == 0 END
BEGIN BOOST_PP_CHECK_EMPTY(OBJECT BOOST_PP_EMPTY()) == 1 END
BEGIN BOOST_PP_CHECK_EMPTY(FUNC(z) BOOST_PP_EMPTY()) == 1 END
BEGIN BOOST_PP_CHECK_EMPTY(FUNC_GEN6) == 0 END
BEGIN BOOST_PP_CHECK_EMPTY(FUNC_GEN7) == 0 END
BEGIN BOOST_PP_CHECK_EMPTY(NAME) == 0 END
BEGIN BOOST_PP_CHECK_EMPTY(ATUPLE) == 0 END
BEGIN BOOST_PP_CHECK_EMPTY(ATUPLE_PLUS) == 0 END
# else
BEGIN 1 == 1 END
# endif