]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/vmd/doc/vmd_modifiers_return_type.qbk
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / vmd / doc / vmd_modifiers_return_type.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_modifiers_return_type Return type modifiers]
9
10 A number of macros are capable of returning the type of
11 data as a v-type rather than, or along with, the
12 data itself. The most obvious of these is BOOST_VMD_GET_TYPE
13 which generically returns the type of the input.
14
15 Return type modifiers turn on, turn off, or change
16 the type of the data returned in some way.
17
18 These modifiers are:
19
20 * BOOST_VMD_RETURN_NO_TYPE, do not return the type of data.
21 * BOOST_VMD_RETURN_TYPE, return the type of data parsing any tuple-like
22 syntactical construct as its most specific type. This means that any
23 tuple-like construct is parsed first as a possible list, next as a
24 possible array if it is not a list, and finally as a tuple if it is not a
25 list or an array.
26 * BOOST_VMD_RETURN_TYPE_LIST, parse any tuple-like syntactical construct
27 first as a possible list and only then as a tuple if it is not a list.
28 * BOOST_VMD_RETURN_TYPE_ARRAY, parse any tuple-like syntactical construct
29 first as a possible array and only then as a tuple if it is not an array.
30 * BOOST_VMD_RETURN_TYPE_TUPLE, parse any tuple-like syntactical construct
31 only as a tuple.
32
33 When VMD parses input generically it must determine the type of each data
34 element of the input. For nearly all of the VMD data types this is never
35 a problem. For the array or list data types this can be a problem, as
36 explained when discussing parsing arrays and lists respectively using the
37 specific macros BOOST_VMD_IS_ARRAY and BOOST_VMD_IS_LIST. The problem is
38 that a valid tuple can be an invalid list or an invalid array, whose
39 parsing as the more specific type will lead to UB.
40 Because of this when VMD parses input generically,
41 and only the data of an element is needed to continue parsing correctly,
42 it parses all tuple-like data as a tuple and never as a list or an array.
43
44 When VMD parses input generically, and the type of the data is required
45 in some way as part of the return of a macro, VMD by default parses for
46 the most specific type of each data element in order to return the most
47 accurate type. In this situation by default the
48 BOOST_VMD_RETURN_TYPE modifier is internally in effect without having
49 to be specified.
50
51 If more than one of the return type modifiers are specified as optional
52 parameters the last one specified is in effect.
53
54 [heading Usage with BOOST_VMD_GET_TYPE]
55
56 The only macro in which VMD without the use of modifiers is being asked
57 to return the type of data is BOOST_VMD_GET_TYPE. For this macro
58 the BOOST_VMD_RETURN_TYPE modifier is internally in effect so if
59 no return type modifiers are input as optional parameters BOOST_VMD_GET_TYPE
60 looks for the most specific type.
61
62 For the BOOST_VMD_GET_TYPE macro the optional return type modifier
63 BOOST_VMD_RETURN_NO_TYPE, if specified, is always ignored since the purpose of
64 BOOST_VMD_GET_TYPE is solely to return the v-type.
65
66 Let's look at how this works with BOOST_VMD_GET_TYPE by specifying VMD sequences
67 that have tuples which may or may not be valid lists or arrays.
68
69 #include <boost/vmd/get_type.hpp>
70
71 #define TUPLE_IS_ARRAY (2,(3,4))
72 #define TUPLE_IS_LIST (anydata,BOOST_PP_NIL)
73 #define TUPLE_IS_LIST_OR_ARRAY (2,(3,BOOST_PP_NIL))
74 #define TUPLE_BUT_INVALID_ARRAY (&2,(3,4))
75 #define TUPLE_BUT_INVALID_LIST (anydata,^BOOST_PP_NIL)
76 #define SEQUENCE_EMPTY
77 #define SEQUENCE_MULTI TUPLE_BUT_INVALID_ARRAY TUPLE_BUT_INVALID_LIST
78
79 BOOST_VMD_GET_TYPE(TUPLE_IS_ARRAY) will return BOOST_VMD_TYPE_ARRAY, the most specific type
80 BOOST_VMD_GET_TYPE(TUPLE_IS_ARRAY,BOOST_VMD_RETURN_TYPE_TUPLE) will return BOOST_VMD_TYPE_TUPLE
81 BOOST_VMD_GET_TYPE(TUPLE_IS_ARRAY,BOOST_VMD_RETURN_TYPE_ARRAY) will return BOOST_VMD_TYPE_ARRAY
82 BOOST_VMD_GET_TYPE(TUPLE_IS_ARRAY,BOOST_VMD_RETURN_TYPE_LIST) will return BOOST_VMD_TYPE_TUPLE
83
84 BOOST_VMD_GET_TYPE(TUPLE_IS_LIST) will return BOOST_VMD_TYPE_LIST, the most specific type
85 BOOST_VMD_GET_TYPE(TUPLE_IS_LIST,BOOST_VMD_RETURN_TYPE_TUPLE) will return BOOST_VMD_TYPE_TUPLE
86 BOOST_VMD_GET_TYPE(TUPLE_IS_LIST,BOOST_VMD_RETURN_TYPE_ARRAY) will return BOOST_VMD_TYPE_TUPLE
87 BOOST_VMD_GET_TYPE(TUPLE_IS_LIST,BOOST_VMD_RETURN_TYPE_LIST) will return BOOST_VMD_TYPE_LIST
88
89 BOOST_VMD_GET_TYPE(TUPLE_IS_LIST_OR_ARRAY) will return BOOST_VMD_TYPE_LIST, the most specific type
90 BOOST_VMD_GET_TYPE(TUPLE_IS_LIST_OR_ARRAY,BOOST_VMD_RETURN_TYPE_TUPLE) will return BOOST_VMD_TYPE_TUPLE
91 BOOST_VMD_GET_TYPE(TUPLE_IS_LIST_OR_ARRAY,BOOST_VMD_RETURN_TYPE_ARRAY) will return BOOST_VMD_TYPE_ARRAY
92 BOOST_VMD_GET_TYPE(TUPLE_IS_LIST_OR_ARRAY,BOOST_VMD_RETURN_TYPE_LIST) will return BOOST_VMD_TYPE_LIST
93
94 BOOST_VMD_GET_TYPE(TUPLE_BUT_INVALID_ARRAY) will give UB
95 BOOST_VMD_GET_TYPE(TUPLE_BUT_INVALID_ARRAY,BOOST_VMD_RETURN_TYPE_TUPLE) will return BOOST_VMD_TYPE_TUPLE
96 BOOST_VMD_GET_TYPE(TUPLE_BUT_INVALID_ARRAY,BOOST_VMD_RETURN_TYPE_ARRAY) will give UB
97 BOOST_VMD_GET_TYPE(TUPLE_BUT_INVALID_ARRAY,BOOST_VMD_RETURN_TYPE_LIST) will return BOOST_VMD_TYPE_TUPLE
98
99 BOOST_VMD_GET_TYPE(TUPLE_BUT_INVALID_LIST) will give UB
100 BOOST_VMD_GET_TYPE(TUPLE_BUT_INVALID_LIST,BOOST_VMD_RETURN_TYPE_TUPLE) will return BOOST_VMD_TYPE_TUPLE
101 BOOST_VMD_GET_TYPE(TUPLE_BUT_INVALID_LIST,BOOST_VMD_RETURN_TYPE_ARRAY) will return BOOST_VMD_TYPE_TUPLE
102 BOOST_VMD_GET_TYPE(TUPLE_BUT_INVALID_LIST,BOOST_VMD_RETURN_TYPE_LIST) will give UB
103
104 BOOST_VMD_GET_TYPE(SEQUENCE_EMPTY)
105 will always return BOOST_VMD_TYPE_EMPTY even if we add any return type modifiers
106 BOOST_VMD_GET_TYPE(SEQUENCE_MULTI)
107 will always return BOOST_VMD_TYPE_SEQUENCE even if we add any return type modifiers
108
109 [heading Usage with sequence converting macros]
110
111 The sequence converting macros converts a sequence to a composite Boost PP data type
112 or to variadic data, where each element's data in the sequence becomes an element in the
113 destination composite type. The macros are:
114
115 * BOOST_VMD_TO_ARRAY, converts the sequence to an array
116 * BOOST_VMD_TO_LIST, converts the sequence to a list
117 * BOOST_VMD_TO_SEQ, converts the sequence to a seq
118 * BOOST_VMD_TO_TUPLE, converts the sequence to a tuple
119 * BOOST_VMD_ENUM, converts the sequence to variadic data
120
121 When it does the conversion, using just the required parameter of the sequence itself,
122 it converts only the data value of each sequence element to the
123 elements of a composite Boost PP data type or variadic data. Because it needs only the data
124 value of each sequence element it determines the type of each sequence element as
125 the most general type that it can be. This means that all tuple-like data are parsed as
126 tuples rather than as possible lists or arrays.
127
128 Using a return type modifier we can convert from a VMD sequence to a
129 Boost PP composite data type or variadic data and retain the type of data of each
130 element in the sequence as part of the conversion. When doing this each of the
131 converted elements of the composite data type becomes a two-element tuple where
132 the first element is the type of the data and the second element is the data itself.
133
134 For the sequence conversion macros the default return type modifier internally set is
135 BOOST_VMD_RETURN_NO_TYPE, which means that the type is not retained.
136 By specifying another optional return type modifier
137 we tell the conversion to preserve the type in the conversion output.
138
139 If the sequence is empty, since there are no sequence elements,
140 any return type modifier we use accomplishes nothing but is fine to use.
141
142 First we show how sequence conversion macros work with the BOOST_VMD_RETURN_TYPE
143 modifier, which always parses for the most specific type.
144
145 #include <boost/vmd/enum.hpp>
146 #include <boost/vmd/to_array.hpp>
147 #include <boost/vmd/to_list.hpp>
148 #include <boost/vmd/to_seq.hpp>
149 #include <boost/vmd/to_tuple.hpp>
150
151 #define BOOST_VMD_REGISTER_ANID (ANID)
152 #define SEQUENCE_EMPTY_1
153 #define SEQUENCE_SINGLE 35
154 #define SEQUENCE_SINGLE_ID ANID
155 #define SEQUENCE_SINGLE_ARRAY (3,(0,1,2))
156 #define SEQUENCE_SINGLE_LIST (data,(more_data,BOOST_PP_NIL))
157 #define SEQUENCE_MULTI_1 (0,1) (2)(3)(4)
158 #define SEQUENCE_MULTI_2 BOOST_VMD_TYPE_SEQ (2,(5,6))
159
160 BOOST_VMD_TO_ARRAY(SEQUENCE_EMPTY_1) will return an empty array '(0,())'
161 BOOST_VMD_TO_ARRAY(SEQUENCE_EMPTY_1,BOOST_VMD_RETURN_TYPE) will return an empty array '(0,())'
162
163 BOOST_VMD_TO_LIST(SEQUENCE_SINGLE) will return a one-element list '(35,BOOST_PP_NIL)'
164 BOOST_VMD_TO_LIST(SEQUENCE_SINGLE,BOOST_VMD_RETURN_TYPE)
165 will return a one-element list '((BOOST_VMD_TYPE_NUMBER,35),BOOST_PP_NIL)'
166
167 BOOST_VMD_TO_SEQ(SEQUENCE_SINGLE_ID) will return a one-element seq '(ANID)'
168 BOOST_VMD_TO_SEQ(SEQUENCE_SINGLE_ID,BOOST_VMD_RETURN_TYPE)
169 will return a one-element seq '((BOOST_VMD_TYPE_IDENTIFIER,ANID))'
170
171 BOOST_VMD_TO_TUPLE(SEQUENCE_SINGLE_ARRAY) will return a single element tuple '((3,(0,1,2)))'
172 BOOST_VMD_TO_TUPLE(SEQUENCE_SINGLE_ARRAY,BOOST_VMD_RETURN_TYPE)
173 will return a single element tuple '((BOOST_VMD_TYPE_ARRAY,(3,(0,1,2))))'
174
175 BOOST_VMD_ENUM(SEQUENCE_SINGLE_LIST) will return the single-element '(data,(more_data,BOOST_PP_NIL))'
176 BOOST_VMD_ENUM(SEQUENCE_SINGLE_LIST,BOOST_VMD_RETURN_TYPE)
177 will return the single element '(BOOST_VMD_TYPE_LIST,(data,(more_data,BOOST_PP_NIL)))'
178
179 BOOST_VMD_TO_TUPLE(SEQUENCE_MULTI_1) will return a multi-element tuple '((0,1),(2)(3)(4))'
180 BOOST_VMD_TO_TUPLE(SEQUENCE_MULTI_1,BOOST_VMD_RETURN_TYPE)
181 will return a multi-element tuple '((BOOST_VMD_TYPE_TUPLE,(0,1)),(BOOST_VMD_TYPE_SEQ,(2)(3)(4)))'
182
183 BOOST_VMD_ENUM(SEQUENCE_MULTI_2) will return multi-element variadic data 'BOOST_VMD_TYPE_SEQ,(2,(5,6))'
184 BOOST_VMD_ENUM(SEQUENCE_MULTI_2,BOOST_VMD_RETURN_TYPE)
185 will return multi-element variadic data '(BOOST_VMD_TYPE_TYPE,BOOST_VMD_TYPE_SEQ),(BOOST_VMD_TYPE_ARRAY,(2,(5,6)))'
186
187 Lets look at how we might use other return type modifiers when doing conversions
188 to avoid UB if we want the type as part of the conversion but
189 the type might be a valid tuple while being an invalid list or array.
190
191 #define TUPLE_IS_VALID_ARRAY (2,(3,4))
192 #define TUPLE_IS_VALID_LIST (anydata,BOOST_PP_NIL)
193 #define TUPLE_BUT_INVALID_ARRAY_2 (&2,(3,4))
194 #define TUPLE_BUT_INVALID_LIST_2 (anydata,^BOOST_PP_NIL)
195
196 #define SEQUENCE_MULTI_T1 TUPLE_IS_VALID_ARRAY TUPLE_IS_VALID_LIST
197 #define SEQUENCE_MULTI_T2 TUPLE_BUT_INVALID_ARRAY_2 TUPLE_IS_VALID_LIST
198 #define SEQUENCE_MULTI_T3 TUPLE_IS_VALID_ARRAY TUPLE_BUT_INVALID_LIST_2
199 #define SEQUENCE_MULTI_T4 TUPLE_BUT_INVALID_ARRAY_2 TUPLE_BUT_INVALID_LIST_2
200
201 We present a number of uses of various sequence conversions
202 with each of our four different sequences, and show their results.
203
204 #include <boost/vmd/to_seq.hpp>
205
206 BOOST_VMD_TO_SEQ(SEQUENCE_MULTI_T1,BOOST_VMD_RETURN_TYPE)
207 will return the seq '((BOOST_VMD_TYPE_ARRAY,(2,(3,4)))) ((BOOST_VMD_TYPE_LIST,(anydata,BOOST_PP_NIL)))'
208 BOOST_VMD_TO_SEQ(SEQUENCE_MULTI_T1,BOOST_VMD_RETURN_TYPE_ARRAY)
209 will return the seq '((BOOST_VMD_TYPE_ARRAY,(2,(3,4)))) ((BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL)))'
210 BOOST_VMD_TO_SEQ(SEQUENCE_MULTI_T1,BOOST_VMD_RETURN_TYPE_LIST)
211 will return the seq '((BOOST_VMD_TYPE_TUPLE,(2,(3,4)))) ((BOOST_VMD_TYPE_LIST,(anydata,BOOST_PP_NIL)))'
212 BOOST_VMD_TO_SEQ(SEQUENCE_MULTI_T1,BOOST_VMD_RETURN_TYPE_TUPLE)
213 will return the seq '((BOOST_VMD_TYPE_TUPLE,(2,(3,4)))) ((BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL)))'
214
215 The SEQUENCE_MULTI_T1 is a valid array followed by a valid list. All return type
216 modifiers produce their results without any UBs.
217
218 #include <boost/vmd/to_tuple.hpp>
219
220 BOOST_VMD_TO_TUPLE(SEQUENCE_MULTI_T2,BOOST_VMD_RETURN_TYPE)
221 will produce UB when attempting to parse the invalid array as an array
222 BOOST_VMD_TO_TUPLE(SEQUENCE_MULTI_T2,BOOST_VMD_RETURN_TYPE_ARRAY)
223 will produce UB when attempting to parse the invalid array as an array
224 BOOST_VMD_TO_TUPLE(SEQUENCE_MULTI_T2,BOOST_VMD_RETURN_TYPE_LIST)
225 will return the tuple '((BOOST_VMD_TYPE_TUPLE,(&2,(3,4))),(BOOST_VMD_TYPE_LIST,(anydata,BOOST_PP_NIL)))'
226 BOOST_VMD_TO_TUPLE(SEQUENCE_MULTI_T2,BOOST_VMD_RETURN_TYPE_TUPLE)
227 will return the tuple '((BOOST_VMD_TYPE_TUPLE,(&2,(3,4))),(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL)))'
228
229 The SEQUENCE_MULTI_T2 is an invalid array, but valid tuple, followed by a valid list.
230
231 In sequence conversion we will get UB whenever we use a return type
232 modifier that parses the data type of the invalid array as an array. But if we use
233 the return type modifiers BOOST_VMD_RETURN_TYPE_LIST or BOOST_VMD_RETURN_TYPE_TUPLE
234 we are never parsing the invalid array as an array but as a tuple instead and therefore
235 we successfully return the type of the invalid array as a BOOST_VMD_TYPE_TUPLE.
236
237 #include <boost/vmd/to_array.hpp>
238
239 BOOST_VMD_TO_ARRAY(SEQUENCE_MULTI_T3,BOOST_VMD_RETURN_TYPE)
240 will produce UB when attempting to parse the invalid list as a list
241 BOOST_VMD_TO_ARRAY(SEQUENCE_MULTI_T3,BOOST_VMD_RETURN_TYPE_LIST)
242 will produce UB when attempting to parse the invalid list as a list
243 BOOST_VMD_TO_ARRAY(SEQUENCE_MULTI_T3,BOOST_VMD_RETURN_TYPE_ARRAY)
244 will return the array '(2,((BOOST_VMD_TYPE_ARRAY,(2,(3,4))),(BOOST_VMD_TYPE_TUPLE,(anydata,^BOOST_PP_NIL))))'
245 BOOST_VMD_TO_ARRAY(SEQUENCE_MULTI_T3,BOOST_VMD_RETURN_TYPE_TUPLE)
246 will return the array '(2,((BOOST_VMD_TYPE_TUPLE,(2,(3,4))),(BOOST_VMD_TYPE_TUPLE,(anydata,^BOOST_PP_NIL))))'
247
248 The SEQUENCE_MULTI_T3 is a valid array followed by an invalid list, but a valid tuple.
249
250 In sequence conversion we will get UBs whenever we use a return type
251 modifier that parses the data type of the invalid list as a list. But if we use
252 the return type modifiers BOOST_VMD_RETURN_TYPE_ARRAY or BOOST_VMD_RETURN_TYPE_TUPLE
253 we are never parsing the invalid list as a list but as a tuple instead and therefore
254 we successfully return the type of the invalid list as a BOOST_VMD_TYPE_TUPLE.
255
256 #include <boost/vmd/to_list.hpp>
257
258 BOOST_VMD_TO_LIST(SEQUENCE_MULTI_T4,BOOST_VMD_RETURN_TYPE)
259 will produce UB when attempting to parse the invalid array or invalid list
260 BOOST_VMD_TO_LIST(SEQUENCE_MULTI_T4,BOOST_VMD_RETURN_TYPE_ARRAY)
261 will produce UB when attempting to parse the invalid array
262 BOOST_VMD_TO_LIST(SEQUENCE_MULTI_T4,BOOST_VMD_RETURN_TYPE_LIST)
263 will produce UB when attempting to parse the invalid list
264 BOOST_VMD_TO_LIST(SEQUENCE_MULTI_T4,BOOST_VMD_RETURN_TYPE_TUPLE)
265 will return the list '((BOOST_VMD_TYPE_TUPLE,(&2,(3,4))),((BOOST_VMD_TYPE_TUPLE,(anydata,^BOOST_PP_NIL)),BOOST_PP_NIL))'
266
267 The SEQUENCE_MULTI_T4 is an invalid array, but valid tuple, followed by an invalid list, but valid tuple.
268
269 In sequence conversion we will get UBs whenever we use a return type
270 modifier that parses the sequence other than looking for only valid tuples. So here we must use
271 the return type modifier BOOST_VMD_RETURN_TYPE_TUPLE for a sequence conversion without
272 generating UBs.
273
274 [heading Usage with BOOST_VMD_ELEM]
275
276 The default functionality of BOOST_VMD_ELEM when the required parameters are used
277 is to return the particular element's data. When BOOST_VMD_ELEM does this it parses
278 all elements of the sequence by determining the most general type of data for each
279 element. The parsing algorithm stops when it reaches the element number whose data
280 is returned. This means that all tuple-like data are parsed as tuples rather than
281 as possible lists or arrays.
282
283 Using return type modifiers as optional parameters we can tell BOOST_VMD_ELEM to
284 return the type of the element found, as well as its data, in the form of a two
285 element tuple. The first element of the tuple is the type of the data and the
286 second element of the tuple is the data itself.
287
288 When we use a return type modifier with BOOST_VMD_ELEM, which tells us to return
289 the type of the data along with the data, the particular modifier only tells
290 BOOST_VMD_ELEM how to parse the type of data for the element found.
291 BOOST_VMD_ELEM will continue to parse elements in the sequence preceding the
292 element found by determining the most general type of the data since this is
293 the safest way of parsing the data itself.
294
295 Using the return type modifier BOOST_VMD_RETURN_TYPE with BOOST_VMD_ELEM is
296 perfectly safe as long as the particular element found is not an invalid list
297 or array, but a valid tuple. It is when the element found may be an invalid
298 list or invalid array that we must use other return type modifiers in order
299 to parse the type of the element correctly.
300
301 #include <boost/vmd/elem.hpp>
302
303 #define BOOST_VMD_REGISTER_ANID_E (ANID_E)
304 #define SEQUENCE_SINGLE_E 35
305 #define SEQUENCE_SINGLE_E2 ANID_E
306 #define SEQUENCE_MULTI_E (0,1) (2)(3)(4)
307 #define SEQUENCE_MULTI_E_2 BOOST_VMD_TYPE_SEQ (2,(5,6))
308
309 BOOST_VMD_ELEM(0,SEQUENCE_SINGLE_E) will return '35'
310 BOOST_VMD_ELEM(0,SEQUENCE_SINGLE_E,BOOST_VMD_RETURN_TYPE) will return '(BOOST_VMD_TYPE_NUMBER,35)'
311
312 BOOST_VMD_ELEM(0,SEQUENCE_SINGLE_E2) will return 'ANID_E'
313 BOOST_VMD_ELEM(0,SEQUENCE_SINGLE_E2,BOOST_VMD_RETURN_TYPE) will return '(BOOST_VMD_TYPE_IDENTIFIER,ANID_E)'
314
315 BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E) will return '(2)(3)(4)'
316 BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E,BOOST_VMD_RETURN_TYPE) will return '(BOOST_VMD_TYPE_SEQ,(2)(3)(4))'
317
318 BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E_2) will return 'BOOST_VMD_TYPE_SEQ'
319 BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E_2,BOOST_VMD_RETURN_TYPE) will return '(BOOST_VMD_TYPE_TYPE,BOOST_VMD_TYPE_SEQ)'
320
321 When we use the other return type modifiers with BOOST_VMD_ELEM we do so
322 because the element we want may be an invalid list or an invalid array
323 but a valid tuple and yet we still want its type returned as part of the result.
324
325 Let's look at how this works with BOOST_VMD_ELEM by specifying VMD sequences
326 that have tuples which are in the form of arrays or lists which cannot be
327 parsed as such by VMD without generating UBs.
328
329 #define TUPLE_IS_VALID_ARRAY_E (2,(3,4))
330 #define TUPLE_IS_VALID_LIST_E (anydata,BOOST_PP_NIL)
331 #define TUPLE_BUT_INVALID_ARRAY_E (&2,(3,4))
332 #define TUPLE_BUT_INVALID_LIST_E (anydata,^BOOST_PP_NIL)
333
334 #define SEQUENCE_MULTI_E1 TUPLE_IS_VALID_ARRAY_E TUPLE_IS_VALID_LIST_E
335 #define SEQUENCE_MULTI_E2 TUPLE_BUT_INVALID_ARRAY_E TUPLE_IS_VALID_LIST_E
336 #define SEQUENCE_MULTI_E3 TUPLE_IS_VALID_ARRAY_E TUPLE_BUT_INVALID_LIST_E
337 #define SEQUENCE_MULTI_E4 TUPLE_BUT_INVALID_ARRAY_E TUPLE_BUT_INVALID_LIST_E
338
339 We present a number of uses of BOOST_VMD_ELEM with each of our four
340 different sequences, and show their results.
341
342 #include <boost/vmd/elem.hpp>
343
344 BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E1,BOOST_VMD_RETURN_TYPE) will return '(BOOST_VMD_TYPE_ARRAY,(2,(3,4)))'
345 BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E1,BOOST_VMD_RETURN_TYPE_ARRAY) will return '(BOOST_VMD_TYPE_ARRAY,(2,(3,4)))'
346 BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E1,BOOST_VMD_RETURN_TYPE_LIST) will return '(BOOST_VMD_TYPE_TUPLE,(2,(3,4)))'
347 BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E1,BOOST_VMD_RETURN_TYPE_TUPLE) will return '(BOOST_VMD_TYPE_TUPLE,(2,(3,4)))'
348 BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E1,BOOST_VMD_RETURN_TYPE) will return '(BOOST_VMD_TYPE_LIST,(anydata,BOOST_PP_NIL))'
349 BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E1,BOOST_VMD_RETURN_TYPE_ARRAY) will return '(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL))'
350 BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E1,BOOST_VMD_RETURN_TYPE_LIST) will return '(BOOST_VMD_TYPE_LIST,(anydata,BOOST_PP_NIL))'
351 BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E1,BOOST_VMD_RETURN_TYPE_TUPLE) will return '(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL))'
352
353 The SEQUENCE_MULTI_E1 is a valid array followed by a valid list. All return type
354 modifiers produce their results without any UBs.
355
356 #include <boost/vmd/elem.hpp>
357
358 BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E2,BOOST_VMD_RETURN_TYPE)
359 will produce UB when attempting to parse the invalid array as an array
360 BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E2,BOOST_VMD_RETURN_TYPE_ARRAY)
361 will produce UB when attempting to parse the invalid array as an array
362 BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E2,BOOST_VMD_RETURN_TYPE_LIST) will return '(BOOST_VMD_TYPE_TUPLE,(&2,(3,4)))'
363 BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E2,BOOST_VMD_RETURN_TYPE_TUPLE) will return '(BOOST_VMD_TYPE_TUPLE,(&2,(3,4)))'
364 BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E2,BOOST_VMD_RETURN_TYPE) will return '(BOOST_VMD_TYPE_LIST,(anydata,BOOST_PP_NIL))'
365 BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E2,BOOST_VMD_RETURN_TYPE_ARRAY) will return '(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL))'
366 BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E2,BOOST_VMD_RETURN_TYPE_LIST) will return '(BOOST_VMD_TYPE_LIST,(anydata,BOOST_PP_NIL))'
367 BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E2,BOOST_VMD_RETURN_TYPE_TUPLE) will return '(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL))'
368
369 The SEQUENCE_MULTI_E2 is an invalid array, but valid tuple, followed by a valid list.
370
371 When we access element 0 of our sequence, and use a return type modifier that parses
372 its data type as an array we will get UB. But if we use the return
373 type modifiers BOOST_VMD_RETURN_TYPE_LIST or BOOST_VMD_RETURN_TYPE_TUPLE
374 we are never parsing the invalid array as an array but as a tuple instead and therefore
375 we successfully return the type of the invalid array as a BOOST_VMD_TYPE_TUPLE.
376
377 When we access element 1 of our sequence, which is both a valid list and a valid tuple,
378 we will never get UB. We will get the return type of the element based
379 on which return type modifier we use.
380
381 #include <boost/vmd/elem.hpp>
382
383 BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E3,BOOST_VMD_RETURN_TYPE) will return '(BOOST_VMD_TYPE_ARRAY,(2,(3,4)))'
384 BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E3,BOOST_VMD_RETURN_TYPE_ARRAY) will return '(BOOST_VMD_TYPE_ARRAY,(2,(3,4)))'
385 BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E3,BOOST_VMD_RETURN_TYPE_LIST) will return '(BOOST_VMD_TYPE_TUPLE,(2,(3,4)))'
386 BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E3,BOOST_VMD_RETURN_TYPE_TUPLE) will return '(BOOST_VMD_TYPE_TUPLE,(2,(3,4)))'
387 BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E3,BOOST_VMD_RETURN_TYPE)
388 will produce UB when attempting to parse the invalid list as a list
389 BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E3,BOOST_VMD_RETURN_TYPE_ARRAY) will return '(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL))'
390 BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E3,BOOST_VMD_RETURN_TYPE_LIST)
391 will produce UB when attempting to parse the invalid list as a list
392 BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E3,BOOST_VMD_RETURN_TYPE_TUPLE) will return '(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL))'
393
394 The SEQUENCE_MULTI_E3 is a valid array followed by an invalid list, but valid tuple.
395
396 When we access element 0 of our sequence, which is both a valid array and a valid tuple,
397 we will never get UB. We will get the return type of the element based
398 on which return type modifier we use.
399
400 When we access element 1 of our sequence, and use a return type modifier that parses
401 its data type as a list we will get UB. But if we use the return
402 type modifiers BOOST_VMD_RETURN_TYPE_ARRAY or BOOST_VMD_RETURN_TYPE_TUPLE
403 we are never parsing the invalid list as a list but as a tuple instead and therefore
404 we successfully return the type of the invalid list as a BOOST_VMD_TYPE_TUPLE.
405
406 #include <boost/vmd/elem.hpp>
407
408 BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E4,BOOST_VMD_RETURN_TYPE)
409 will produce UB when attempting to parse the invalid array
410 BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E4,BOOST_VMD_RETURN_TYPE_ARRAY)
411 will produce UB when attempting to parse the invalid array
412 BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E4,BOOST_VMD_RETURN_TYPE_LIST) will return '(BOOST_VMD_TYPE_TUPLE,(2,(3,4)))'
413 BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E4,BOOST_VMD_RETURN_TYPE_TUPLE) will return '(BOOST_VMD_TYPE_TUPLE,(2,(3,4)))'
414 BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E4,BOOST_VMD_RETURN_TYPE)
415 will produce UB when attempting to parse the invalid list
416 BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E4,BOOST_VMD_RETURN_TYPE_ARRAY) will return '(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL))'
417 BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E4,BOOST_VMD_RETURN_TYPE_LIST)
418 will produce UB when attempting to parse the invalid list
419 BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E4,BOOST_VMD_RETURN_TYPE_TUPLE) will return '(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL))'
420
421 The SEQUENCE_MULTI_E4 is an invalid array, but valid tuple, followed by an invalid list, but valid tuple.
422
423 When we access element 0 of our sequence, which is an invalid array but a valid tuple,
424 we must use a return type modifier which does not parse element 0 as an array, else
425 we will get UB. This means we must use the return
426 type modifiers BOOST_VMD_RETURN_TYPE_LIST or BOOST_VMD_RETURN_TYPE_TUPLE so
427 we are never parsing the invalid array as an array but as a tuple instead and therefore
428 we successfully return the type of the invalid array as a BOOST_VMD_TYPE_TUPLE.
429
430 When we access element 1 of our sequence, which is an invalid list but a valid tuple,
431 we must use a return type modifier which does not parse element 1 as a list, else
432 we will get UB. This means we must use the return
433 type modifiers BOOST_VMD_RETURN_TYPE_ARRAY or BOOST_VMD_RETURN_TYPE_TUPLE so
434 we are never parsing the invalid list as a list but as a tuple instead and therefore
435 we successfully return the type of the invalid list as a BOOST_VMD_TYPE_TUPLE.
436
437 [heading Usage with other modifiers of BOOST_VMD_ELEM]
438
439 We have not yet discussed the rest of the modifiers which may be
440 used with BOOST_VMD_ELEM, but return type modifiers are completely
441 independent of any of them. This means they can be combined with
442 other modifiers and whenever the element of the sequence is
443 returned the return type modifiers determine of what the value of that
444 element consists; whether it be just the element data or the element
445 as a type/data tuple with the type parsed according to our return type
446 modifier. When we subsequently discuss the use of other modifiers with
447 BOOST_VMD_ELEM and refer to the element being returned, we are referring
448 to that element as it is determined by the return type modifiers, which
449 by default only returns the element's data.
450
451 [endsect]