12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 |
- [/
- (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]
|