77 lines
5.2 KiB
Plaintext
77 lines
5.2 KiB
Plaintext
[/
|
|
(C) Copyright Edward Diener 2011-2015
|
|
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).
|
|
]
|
|
|
|
[section:vmd_constraints Macro constraints]
|
|
|
|
When discussing the BOOST_VMD_IS_EMPTY macro I mentioned constraining input to
|
|
the macro. Now I will discuss what this means in terms of preprocessor metaprogramming
|
|
and input to macros in general.
|
|
|
|
[heading Constrained input]
|
|
|
|
When a programmer designs any kinds of callables in C++ ( functions, member functions etc. ),
|
|
he specifies what the types of input and the return value are. The C++ compiler enforces this
|
|
specification at compile time. Similarly at run-time a callable may check that its
|
|
input falls within certain documented and defined boundaries and react accordingly
|
|
if it does not. This is all part of the constraints for any callable in C++ and should
|
|
be documented by any good programmer.
|
|
|
|
The C++ preprocessor is much "dumber" than the C++ compiler and even with the preprocessor
|
|
metaprogramming constructs which Paul Mensonides has created in Boost PP there is far less
|
|
the preprocessor metaprogrammer can do at preprocessing time to constrain argument input
|
|
to a macro than a programmer can do at compile-time and/or at run-time to constrain argument
|
|
input to a C++ callable. Nevertheless it is perfectly valid to document what a macro expects
|
|
as its argument input and, if a programmer does not follow the constraint, the macro will fail
|
|
to work properly. In the ideal case in preprocessor metaprogramming the macro could tell whether
|
|
or not the constraint was met and could issue some sort of intelligible preprocessing error
|
|
when this occurred, but even within the reality of preprocessor metaprogramming with Boost PP
|
|
this is not always possible to do. Nevertheless if the user of a macro
|
|
does not follow the constraints for a macro parameter, as specified in the
|
|
documentation of a particular macro being invoked, any error which occurs is the
|
|
fault of that user. I realize that this may go against the strongly
|
|
held concept that programming errors must always be met with some sort of compile-time or
|
|
run-time occurrence which allows the programmer to correct the error, rather than a silent failure
|
|
which masks the error. Because the preprocessor is "dumber" and cannot provide this occurrence
|
|
in all cases the error could unfortunately be masked, despite the fact that the documentation
|
|
specifies the correct input constraint(s). In the case of the already discussed
|
|
macro BOOST_VMD_IS_EMPTY, this masking of the error could only occur with a preprocessor ( Visual C++ )
|
|
which is not C++ standard conformant.
|
|
|
|
The Boost PP library does have a way of generating a preprocessing error, without generating preprocessor
|
|
output, but once again this way does not work with the non-conformant preprocessor of Visual C++. The means
|
|
to do so using Boost PP is through the BOOST_PP_ASSERT macro. As will be seen and discussed later VMD has
|
|
an equivalent macro which will work with Visual C++ by producing incorrect C++ output rather than a preprocessing
|
|
error, but even this is not a complete solution since the incorrect C++ output produced could be hidden.
|
|
|
|
Even the effort to produce a preprocessing error, or incorrect output inducing a compile-time error,
|
|
does not solve the problem of constrained input for preprocessor metaprogramming. Often it is impossible
|
|
to determine if the input meets the constraints which the preprocessor metaprogrammer places on it and
|
|
documents. Certain preprocessing tokens cannot be checked reliably for particular values, or a range of
|
|
values, without the checking mechanism itself creating a preprocessing error or undefined behavior.
|
|
|
|
This does not mean that one should give up attempting to check macro input constraints. If it can be done
|
|
I see the value of such checks and a number of VMD macros, discussed later, are designed as preprocessing
|
|
input constraint checking macros. But the most important thing when dealing with macro input constraints is
|
|
that they should be carefully documented, and that the programmer should know that if the constraints are
|
|
not met either preprocessing errors or incorrect macro results could be the results.
|
|
|
|
The VMD library, in order to present more preprocessor programming functionality and
|
|
flexibility, allows that erroneous results could occur if certain input constraints are not met, whether the
|
|
erroneous results are preprocessing errors or incorrect output from a VMD macro. At the same time the VMD does
|
|
everything that the preprocessor is capable of doing to check the input constraints, and carefully documents
|
|
for each macro in the library what the input for each could be in order to avoid erroneous output.
|
|
|
|
Documented macro input constraints are just as valid in the preprocessor as
|
|
compile-time/run-time constraints are valid in C++, even if the detection of such constraints
|
|
and/or the handling of constraints that are not met are far more difficult,
|
|
if not impossible, in the preprocessor than in the compile-time/run-time processing of C++.
|
|
|
|
The VMD library uses constraints for most of it macros and the documentation for those macros
|
|
mentions the constraints that apply in order to use the macro.
|
|
|
|
[endsect]
|