]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/vmd/doc/vmd_empty.qbk
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / vmd / doc / vmd_empty.qbk
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]