]>
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_test_empty Emptiness] | |
9 | ||
10 | [heading Passing empty arguments] | |
11 | ||
12 | It is possible to pass an empty argument to a macro. | |
13 | The official terminology for this in the C++ standard is an argument | |
14 | "consisting of no preprocessing tokens". | |
15 | ||
16 | Let us consider a number of cases without worrying too much | |
17 | what the macro output represents. | |
18 | ||
19 | Consider these two function-like macros: | |
20 | ||
21 | #define SMACRO() someoutput | |
22 | #define EMACRO(x) otheroutput x | |
23 | ||
24 | The first macro takes no parameters so invoking it must always be done by | |
25 | ||
26 | SMACRO() | |
27 | ||
28 | and passing any arguments to it would be invalid. | |
29 | ||
30 | The second macro takes a single parameter. it can be evoked as | |
31 | ||
32 | EMACRO(somedata) | |
33 | ||
34 | but it also can be invoked as | |
35 | ||
36 | EMACRO() | |
37 | ||
38 | In the second invocation of EMACRO we are passing an empty argument to the macro. | |
39 | Similarly for any macro having 1 or more parameters, an empty argument | |
40 | can be validly passed for any of the parameters, as in | |
41 | ||
42 | #define MMACRO(x,y,z) x y z | |
43 | ||
44 | MMACRO(1,,2) | |
45 | ||
46 | An empty argument is an argument even if we are passing nothing. | |
47 | ||
48 | Because an empty argument can be passed for a given parameter of | |
49 | a macro does not mean one should do so. Any given macro will specify what each | |
50 | argument to a macro should represent, and it is has normally been very rare to encounter | |
51 | a macro which specifies that an empty argument can logically be passed for a given | |
52 | argument. But from the perspective of standard C++ it is perfectly valid to | |
53 | pass an empty argument for a macro parameter. | |
54 | ||
55 | The notion of passing empty arguments can be extended to passing empty data which | |
56 | "consists of no preprocessing tokens" in slightly more complicated situations. | |
57 | It is possible to pass empty data as an argument to a variadic macro in the form of | |
58 | variadic macro data, as in | |
59 | ||
60 | #define VMACRO(x,...) x __VA_ARGS__ | |
61 | ||
62 | invoked as | |
63 | ||
64 | VMACRO(somedata,) | |
65 | ||
66 | Here one passes empty data as the variadic macro data and it is perfectly valid C++. | |
67 | Please notice that this different from | |
68 | ||
69 | VMACRO(somedata) | |
70 | ||
71 | which is not valid C++ since something must be passed for the variadic argument. | |
72 | Similar one could invoke the macro as | |
73 | ||
74 | VMACRO(somedata,vdata1,,vdata3) | |
75 | ||
76 | where one is passing variadic macro data but an element in the variadic macro data is empty. | |
77 | ||
78 | Furthermore if we are invoking a macro which expects a Boost PP data type, such as | |
79 | a tuple, we could also validly pass empty data for all or part of the data in a tuple, | |
80 | as in | |
81 | ||
82 | #define TMACRO(x,atuple) x atuple | |
83 | ||
84 | TMACRO(somedata,()) | |
85 | ||
86 | In this case we are passing a 1 element tuple | |
87 | where the single element itself is empty. | |
88 | ||
89 | or | |
90 | ||
91 | TMACRO(somedata,(telem1,,telem2,teleem3)) | |
92 | ||
93 | In this case we are passing a 4 element tuple where | |
94 | the second element is empty. | |
95 | ||
96 | Again either invocation is valid C++ but it is not necessarily what the | |
97 | designed of the macro has desired, even if in both cases the macro designer | |
98 | has specified that the second parameter must be a tuple for the macro | |
99 | to work properly. | |
100 | ||
101 | [heading Returning emptiness] | |
102 | ||
103 | Similar to passing empty arguments in various ways to a macro, | |
104 | the data which a macro returns ( or 'generates' may be a better term ) | |
105 | could be empty, in various ways. Again I am not necessarily promoting | |
106 | this idea as a common occurrence of macro design but merely pointing it | |
107 | out as valid C++ preprocessing. | |
108 | ||
109 | #define RMACRO(x,y,z) | |
110 | ||
111 | RMACRO(data1,data2,data3) | |
112 | ||
113 | It is perfectly valid C++ to return "nothing" from a macro invocation. | |
114 | In fact a number of macros in Boost PP do that based on the preprocessor | |
115 | metaprogramming logic of the macro, and are documented as such. | |
116 | ||
117 | Similarly one could return nothing as part or all of a Boost PP | |
118 | data type or even as part of variadic macro data. | |
119 | ||
120 | #define TRETMACRO(x,y,z) () | |
121 | #define TRETMACRO1(x,y,z) (x,,y,,z) | |
122 | #define VRETMACRO(x,y,z) x,,y,,z | |
123 | ||
124 | Here again we are returning something but in terms of a Boost PP | |
125 | tuple or in terms of variadic data, we have elements which are empty. | |
126 | ||
127 | [heading Emptiness in preprocessor metaprogramming] | |
128 | ||
129 | In the examples given above where "emptiness" in one form of another | |
130 | is passed as arguments to a macro or returned from a macro, the examples | |
131 | I have given were created as simplified as possible to illustrate my points. | |
132 | In actual preprocessor metaprogramming, using Boost PP, where complicated logic | |
133 | is used to generate macro output based on the arguments to a macro, it might be | |
134 | useful to allow and work with empty data if one were able to test for the fact | |
135 | that data was indeed empty. | |
136 | ||
137 | [heading Testing for empty data] | |
138 | ||
139 | Currently Boost PP has an undocumented macro for testing whether | |
140 | a parameter is empty of not, written without the use of variadic | |
141 | macros. The macro is called BOOST_PP_IS_EMPTY. The macro is by its nature flawed, | |
142 | since there is no generalized way of determining whether or not a | |
143 | parameter is empty using the C++ preprocessor. But the macro will | |
144 | work given input limited in various ways or if the input is actually empty. | |
145 | ||
146 | Paul Mensonides, the developer of Boost PP and the BOOST_PP_IS_EMPTY macro | |
147 | in that library, also wrote a better macro using variadic | |
148 | macros, for determining whether or not a parameter is empty or not, which | |
149 | he published on the Internet in response to a discussion about emptiness. | |
150 | This macro is also not perfect, since there is no perfect solution, | |
151 | but will work correctly with almost all input. I have adapted his code | |
152 | for the VMD and developed my own very slightly different code. | |
153 | ||
154 | The macro is called [macroref BOOST_VMD_IS_EMPTY] and will return 1 if its input | |
155 | is empty or 0 if its input is not empty. The macro | |
156 | is a variadic macro which make take any input | |
157 | [footnote For VC++ 8 the input is not variadic data but a single parameter]. | |
158 | ||
159 | [heading Macro Flaw with a standard C++ compiler] | |
160 | ||
161 | The one situation where the macro always does not work properly is if its input resolves | |
162 | to a function-like macro name or a sequence of preprocessor tokens ending with | |
163 | a function-like macro name and the function-like macro takes two or more parameters. | |
164 | ||
165 | Here is a simple example: | |
166 | ||
167 | #include <boost/vmd/is_empty.hpp> | |
168 | ||
169 | #define FMACRO(x,y) any_output | |
170 | ||
171 | BOOST_VMD_IS_EMPTY(FMACRO) | |
172 | BOOST_VMD_IS_EMPTY(some_input FMACRO) | |
173 | ||
174 | In the first case the name of a function-like macro is being passed to | |
175 | BOOST_VMD_IS_EMPTY while in the second case a sequence of preprocessing tokens is being | |
176 | passed to BOOST_VMD_IS_EMPTY ending with the name of a function-like macro. | |
177 | The function-like macro also has two ( or more ) parameters. In both the | |
178 | cases above a compiler error will result from the use of BOOST_VMD_IS_EMPTY. | |
179 | ||
180 | Please note that these two problematical cases are not the same as passing | |
181 | an invocation of a function-like macro name to BOOST_VMD_IS_EMPTY, as in | |
182 | ||
183 | #include <boost/vmd/is_empty.hpp> | |
184 | ||
185 | BOOST_VMD_IS_EMPTY(FMACRO(arg1,arg2)) | |
186 | BOOST_VMD_IS_EMPTY(someinput FMACRO(arg1,arg2)) | |
187 | ||
188 | which always works correctly, unless of course a particular function-like macro | |
189 | invocation resolves to either of our two previous situations. | |
190 | ||
191 | Another situation where the macro may not work properly is if the previously mentioned | |
192 | function-like macro takes a single parameter but creates an error when the argument | |
193 | passed is empty. An example of this would be: | |
194 | ||
195 | #define FMACRO(x) BOOST_PP_CAT(+,x C); | |
196 | ||
197 | When nothing is passed to FMACRO undefined behavior will occur since attempting to concatenate | |
198 | '+' to ' C' is UB in C++ preprocessor terms. | |
199 | ||
200 | So for a standard conforming compiler we have essentially a single corner case where | |
201 | the BOOST_VMD_IS_EMPTY does not work and, when it does not work it, produces a | |
202 | compiler error rather than an incorrect result. Essentially what is desired for maximum | |
203 | safety is that we never pass input ending with the name of a function-like macro name when | |
204 | testing for emptiness. | |
205 | ||
206 | [heading Macro Flaw with Visual C++] | |
207 | ||
208 | The VC++ preprocessor is not a standard C++ conforming preprocessor in at least two | |
209 | relevant situations to our discussion of emptiness. These situations combine to create | |
210 | a single corner case which causes the BOOST_VMD_IS_EMPTY macro to not work properly | |
211 | using VC++ when the input resolves to a function-like macro name. | |
212 | ||
213 | The first situation, related to our discussion of emptiness, where the VC++ preprocessor | |
214 | is not a standard C++ conforming preprocessor is that if a macro taking 'n' number of parameters is invoked | |
215 | with 0 to 'n-1' parameters, the compiler does not give an error, but only a warning. | |
216 | ||
217 | #define FMACRO(x,y) x + y | |
218 | ||
219 | FMACRO(1) | |
220 | ||
221 | should give a compiler error, as it does when using a C++ standard-conforming | |
222 | compiler, but when invoked using VC++ it only gives a warning | |
223 | and VC++ continues macro substitution with 'y' as a placemarker preprocessing token. | |
224 | This non-standard conforming action actually eliminates the case where BOOST_VMD_IS_EMPTY | |
225 | does not work properly with a standard C++ conforming compiler. But of course it has the | |
226 | potential of producing incorrect output in other macro processing situations unrelated | |
227 | to the BOOST_VMD_IS_EMPTY invocation, where a compiler error should occur. | |
228 | ||
229 | A second general situation, related to our discussion of emptiness, where the VC++ preprocessor | |
230 | is not a standard C++ conforming preprocessor is that the expansion of a macro works incorrectly | |
231 | when the expanded macro is a function-like macro name followed by a function-like macro invocation, | |
232 | in which case the macro re-expansion is erroneously done more than once. This latter case can be | |
233 | seen by this example: | |
234 | ||
235 | #define FMACRO1(parameter) FMACRO3 parameter() | |
236 | #define FMACRO2() () | |
237 | #define FMACRO3() 1 | |
238 | ||
239 | FMACRO1(FMACRO2) | |
240 | ||
241 | should expand to: | |
242 | ||
243 | FMACRO3() | |
244 | ||
245 | but in VC++ it expands to: | |
246 | ||
247 | 1 | |
248 | ||
249 | where after initially expanding the macro to: | |
250 | ||
251 | FMACRO3 FMACRO2() | |
252 | ||
253 | VC++ erroneously rescans the sequence of preprocessing tokens more than once rather than | |
254 | rescan just one more time for more macro names. | |
255 | ||
256 | What these two particular preprocessor flaws in the VC++ compiler mean is that although | |
257 | BOOST_VMD_IS_EMPTY does not fail with a compiler error in the same case as with | |
258 | a standard C++ conforming compiler given previously, it fails by giving | |
259 | the wrong result in another situation. | |
260 | ||
261 | The failing situation is: | |
262 | ||
263 | when the input to BOOST_VMD_IS_EMPTY resolves to only a function-like macro | |
264 | name, and the function-like macro, when passed a single empty argument, expands to | |
265 | a Boost PP tuple, BOOST_VMD_IS_EMPTY will erroneously return 1 when using the Visual C++ | |
266 | compiler rather than either give a preprocessing error or return 0. | |
267 | ||
268 | Here is an example of the failure: | |
269 | ||
270 | #include <boost/vmd/is_empty.hpp> | |
271 | ||
272 | #define FMACRO4() ( any_number_of_tuple_elements ) | |
273 | #define FMACRO5(param) ( any_number_of_tuple_elements ) | |
274 | #define FMACRO6(param1,param2) ( any_number_of_tuple_elements ) | |
275 | ||
276 | BOOST_VMD_IS_EMPTY(FMACRO4) // erroneously returns 1, instead of 0 | |
277 | BOOST_VMD_IS_EMPTY(FMACRO5) // erroneously returns 1, instead of 0 | |
278 | BOOST_VMD_IS_EMPTY(FMACRO6) // erroneously returns 1, instead of generating a preprocessing error | |
279 | ||
280 | As with a standard C++ conforming compiler, we have a rare corner case where | |
281 | the BOOST_VMD_IS_EMPTY will not work properly, but unfortunately in this very | |
282 | similar but even rarer corner case with VC++, we will silently get an incorrect result | |
283 | rather than a compiler error. | |
284 | ||
285 | I want to reiterate that there is no perfect solution in C++ to the detection of | |
286 | emptiness even for a C++ compiler whose preprocessor is completely conformant, which | |
287 | VC++ obviously is not. | |
288 | ||
289 | [heading Macro Flaw conclusion] | |
290 | ||
291 | With all of the above mentioned, the case(s) where BOOST_VMD_IS_EMPTY will work | |
292 | incorrectly are very small, even with the erroneous VC++ preprocessor, | |
293 | and I consider the macro worthwhile to use since it works correctly with the vast | |
294 | majority of possible preprocessor input. | |
295 | ||
296 | The case where it will not work, with both a C++ standard conforming preprocessor or | |
297 | with Visual C++, occurs when the name of a function-like macro is part of the input | |
298 | to BOOST_VMD_IS_EMPTY. Obviously the macro should be used by the preprocessor | |
299 | metaprogrammer when the possible input to it is constrained to eliminate the erroneous | |
300 | case. | |
301 | ||
302 | Furthermore, since emptiness can correctly be tested for in nearly every situation, the | |
303 | BOOST_VMD_IS_EMPTY macro can be used internally when the preprocessor metaprogrammer wants to return data | |
304 | from a macro and all or part of that data could be empty. | |
305 | ||
306 | Therefore I believe the BOOST_VMD_IS_EMPTY macro is quite useful, despite the corner case flaw | |
307 | which makes it imperfect. Consequently I believe that the preprocessor metaprogrammer | |
308 | can use the concept of empty preprocessor data in the design of his own macros. | |
309 | ||
310 | [heading Using the macro] | |
311 | ||
312 | The macro BOOST_VMD_IS_EMPTY is used internally throughout VMD and macro programmers | |
313 | may find this macro useful in their own programming efforts despite the slight flaw | |
314 | in the way that it works. | |
315 | ||
316 | You can use the general header file: | |
317 | ||
318 | #include <boost/vmd/vmd.hpp> | |
319 | ||
320 | or you can use the individual header file: | |
321 | ||
322 | #include <boost/vmd/is_empty.hpp> | |
323 | ||
324 | for the BOOST_VMD_IS_EMPTY macro. | |
325 | ||
326 | [endsect] |