]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | [/ |
2 | (C) Copyright Edward Diener 2011-2015 | |
3 | Distributed under the Boost Software License, Version 1.0. | |
4 | (See accompanying file LICENSE_1_0.txt or copy at | |
5 | http://www.boost.org/LICENSE_1_0.txt). | |
6 | ] | |
7 | ||
8 | [section:vmd_constraints Macro constraints] | |
9 | ||
10 | When discussing the BOOST_VMD_IS_EMPTY macro I mentioned constraining input to | |
11 | the macro. Now I will discuss what this means in terms of preprocessor metaprogramming | |
12 | and input to macros in general. | |
13 | ||
14 | [heading Constrained input] | |
15 | ||
16 | When a programmer designs any kinds of callables in C++ ( functions, member functions etc. ), | |
17 | he specifies what the types of input and the return value are. The C++ compiler enforces this | |
18 | specification at compile time. Similarly at run-time a callable may check that its | |
19 | input falls within certain documented and defined boundaries and react accordingly | |
20 | if it does not. This is all part of the constraints for any callable in C++ and should | |
21 | be documented by any good programmer. | |
22 | ||
23 | The C++ preprocessor is much "dumber" than the C++ compiler and even with the preprocessor | |
24 | metaprogramming constructs which Paul Mensonides has created in Boost PP there is far less | |
25 | the preprocessor metaprogrammer can do at preprocessing time to constrain argument input | |
26 | to a macro than a programmer can do at compile-time and/or at run-time to constrain argument | |
27 | input to a C++ callable. Nevertheless it is perfectly valid to document what a macro expects | |
28 | as its argument input and, if a programmer does not follow the constraint, the macro will fail | |
29 | to work properly. In the ideal case in preprocessor metaprogramming the macro could tell whether | |
30 | or not the constraint was met and could issue some sort of intelligible preprocessing error | |
31 | when this occurred, but even within the reality of preprocessor metaprogramming with Boost PP | |
32 | this is not always possible to do. Nevertheless if the user of a macro | |
33 | does not follow the constraints for a macro parameter, as specified in the | |
34 | documentation of a particular macro being invoked, any error which occurs is the | |
35 | fault of that user. I realize that this may go against the strongly | |
36 | held concept that programming errors must always be met with some sort of compile-time or | |
37 | run-time occurrence which allows the programmer to correct the error, rather than a silent failure | |
38 | which masks the error. Because the preprocessor is "dumber" and cannot provide this occurrence | |
39 | in all cases the error could unfortunately be masked, despite the fact that the documentation | |
40 | specifies the correct input constraint(s). In the case of the already discussed | |
41 | macro BOOST_VMD_IS_EMPTY, this masking of the error could only occur with a preprocessor ( Visual C++ ) | |
42 | which is not C++ standard conformant. | |
43 | ||
44 | The Boost PP library does have a way of generating a preprocessing error, without generating preprocessor | |
45 | output, but once again this way does not work with the non-conformant preprocessor of Visual C++. The means | |
46 | to do so using Boost PP is through the BOOST_PP_ASSERT macro. As will be seen and discussed later VMD has | |
47 | an equivalent macro which will work with Visual C++ by producing incorrect C++ output rather than a preprocessing | |
48 | error, but even this is not a complete solution since the incorrect C++ output produced could be hidden. | |
49 | ||
50 | Even the effort to produce a preprocessing error, or incorrect output inducing a compile-time error, | |
51 | does not solve the problem of constrained input for preprocessor metaprogramming. Often it is impossible | |
52 | to determine if the input meets the constraints which the preprocessor metaprogrammer places on it and | |
53 | documents. Certain preprocessing tokens cannot be checked reliably for particular values, or a range of | |
54 | values, without the checking mechanism itself creating a preprocessing error or undefined behavior. | |
55 | ||
56 | This does not mean that one should give up attempting to check macro input constraints. If it can be done | |
57 | I see the value of such checks and a number of VMD macros, discussed later, are designed as preprocessing | |
58 | input constraint checking macros. But the most important thing when dealing with macro input constraints is | |
59 | that they should be carefully documented, and that the programmer should know that if the constraints are | |
60 | not met either preprocessing errors or incorrect macro results could be the results. | |
61 | ||
62 | The VMD library, in order to present more preprocessor programming functionality and | |
63 | flexibility, allows that erroneous results could occur if certain input constraints are not met, whether the | |
64 | erroneous results are preprocessing errors or incorrect output from a VMD macro. At the same time the VMD does | |
65 | everything that the preprocessor is capable of doing to check the input constraints, and carefully documents | |
66 | for each macro in the library what the input for each could be in order to avoid erroneous output. | |
67 | ||
68 | Documented macro input constraints are just as valid in the preprocessor as | |
69 | compile-time/run-time constraints are valid in C++, even if the detection of such constraints | |
70 | and/or the handling of constraints that are not met are far more difficult, | |
71 | if not impossible, in the preprocessor than in the compile-time/run-time processing of C++. | |
72 | ||
73 | The VMD library uses constraints for most of it macros and the documentation for those macros | |
74 | mentions the constraints that apply in order to use the macro. | |
75 | ||
76 | [endsect] |