]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | [/ |
2 | (C) Copyright Edward Diener 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_empty_ppdata Functionality for "empty" seqs and tuples] | |
9 | ||
10 | Boost PP arrays and lists can be empty but seqs and tuples cannot. | |
11 | The form of an empty array is '(0,())' and the form of an empty | |
12 | list is 'BOOST_PP_NIL'. But the form of '()' does not represent | |
13 | an empty seq or an empty tuple. Instead for a seq it represents | |
14 | a one element seq whose data is empty, while for a tuple it | |
15 | represents a tuple with a size of 1 whose single element is empty. | |
16 | ||
17 | Not having a way to represent an empty seq or tuple represents a | |
18 | small problem for Boost PP users. For a tuple, especially, not being | |
19 | able to be "empty" is the only reason, when variadic macros are supported, | |
20 | why an end-user might prefer to use an array rather than a tuple as | |
21 | Boost PP preprocessor data. Otherwise, when using variadic macros, using | |
22 | a tuple is easier to notate and subsequently use than an array | |
23 | since no effort is needed to specify the number of elements of a tuple. | |
24 | ||
25 | VMD as we have seen has functionality to tell when preprocessor data is "empty" | |
26 | through its BOOST_VMD_IS_EMPTY macro. Because of this it is possible to treat | |
27 | emptiness, when applied to a seq or tuple, as an empty seq or an empty tuple | |
28 | respectively, thus allowing seqs and tuples to be empty, just as arrays and | |
29 | lists are. | |
30 | ||
31 | However there is one large problem when treating emptiness as an empty seq or | |
32 | empty tuple; Boost PP functionality for a seq or tuple knows nothing about it. | |
33 | In other words if you passed emptiness to a Boost PP macro which expects a | |
34 | seq or tuple, such as: | |
35 | ||
36 | BOOST_PP_SEQ_SIZE() | |
37 | ||
38 | or | |
39 | ||
40 | BOOST_PP_TUPLE_PUSH_BACK(,1) | |
41 | ||
42 | you would get UB, undefined behavior. | |
43 | ||
44 | In order to use seqs and tuples which can be empty VMD defines a number | |
45 | of macros which mimic many of those in Boost PP, but begin with BOOST_VMD_ | |
46 | rather than BOOST_PP_. The VMD macros work with what I will call a 'VMD seq' or | |
47 | a 'VMD tuple', while the Boost PP equivalents work with the traditional seq | |
48 | or tuple. A VMD seq is a seq which may be empty and a VMD tuple is a tuple | |
49 | which may be empty. A VMD seq is therefore a superset of a normal seq and a | |
50 | VMD tuple is therefore a superset of a normal tuple. The VMD functionality | |
51 | therefore can accept a VMD seq or tuple or a normal seq or tuple whereas the | |
52 | equivalent Boost PP functionality only accepts a normal seq or tuple. To be more | |
53 | more precise the Boost PP functionality can accept a VMD seq or a VMD tuple as | |
54 | long as it is not empty. In other words there is no difference between a | |
55 | non-empty VMD seq or a Boost PP seq, or between a non-empty VMD tuple and | |
56 | a Boost PP tuple. | |
57 | ||
58 | The particular macros which VMD supplies, supporting VMD seqs and VMD tuples, | |
59 | are divided between array, list, seq, and tuple functionality. The actual header | |
60 | files for these macros are in sub-directories of the VMD directory, which start | |
61 | respectively with 'array','list','seq' and 'tuple'. The header files are all | |
62 | also included in the general boost/vmd/vmd.hpp header file. | |
63 | ||
64 | [heading Array macros] | |
65 | ||
66 | The array macros provide conversions from an array to a VMD seq or a VMD tuple. | |
67 | The array macros are: | |
68 | ||
69 | [table:vpp_array Array macros | |
70 | [[Macro][Parameter][Return][Functionality][Header]] | |
71 | [ | |
72 | [BOOST_VMD_ARRAY_TO_SEQ] | |
73 | [array = a Boost PP array] | |
74 | [A VMD seq] | |
75 | [Converts an array to a VMD seq. If the array is empty the seq is empty, otherwise the conversion is the same as BOOST_PP_ARRAY_TO_SEQ] | |
76 | [boost/vmd/array/to_seq.hpp] | |
77 | ] | |
78 | [ | |
79 | [BOOST_VMD_ARRAY_TO_TUPLE] | |
80 | [array = a Boost PP array] | |
81 | [A VMD tuple] | |
82 | [Converts an array to a VMD tuple. If the array is empty the tuple is empty, otherwise the conversion is the same as BOOST_PP_ARRAY_TO_TUPLE] | |
83 | [boost/vmd/array/to_tuple.hpp] | |
84 | ] | |
85 | ] | |
86 | ||
87 | The difference between the array conversion macros and their equivalent ones | |
88 | in Boost PP is that if the array is empty the VMD macros return emptiness | |
89 | whereas the Boost PP macros have UB. | |
90 | ||
91 | You can include the array macros either using their individual header files, | |
92 | the general 'boost/vmd/array.hpp' header file for all array macros, or the | |
93 | general header file 'boost/vmd/vmd.hpp' for all macros. | |
94 | ||
95 | [heading List macros] | |
96 | ||
97 | The list macros provide conversions from a list to a VMD seq or a VMD tuple. | |
98 | The list macros are: | |
99 | ||
100 | [table:vpp_list List macros | |
101 | [[Macro][Parameter][Return][Functionality][Header]] | |
102 | [ | |
103 | [BOOST_VMD_LIST_TO_SEQ] | |
104 | [list = a Boost PP list] | |
105 | [A VMD seq] | |
106 | [Converts a list to a VMD seq. If the list is empty the seq is empty, otherwise the conversion is the same as BOOST_PP_LIST_TO_SEQ] | |
107 | [boost/vmd/list/to_seq.hpp] | |
108 | ] | |
109 | [ | |
110 | [BOOST_VMD_LIST_TO_TUPLE] | |
111 | [list = a Boost PP list] | |
112 | [A VMD tuple] | |
113 | [Converts a list to a VMD tuple. If the list is empty the tuple is empty, otherwise the conversion is the same as BOOST_PP_LIST_TO_TUPLE] | |
114 | [boost/vmd/list/to_tuple.hpp] | |
115 | ] | |
116 | ] | |
117 | ||
118 | The difference between the list conversion macros and their equivalent ones | |
119 | in Boost PP is that if the list is empty the VMD macros return emptiness | |
120 | whereas the Boost PP macros have UB. | |
121 | ||
122 | You can include the list macros either using their individual header files, | |
123 | the general 'boost/vmd/list.hpp' header file for all list macros, or the | |
124 | general header file 'boost/vmd/vmd.hpp' for all macros. | |
125 | ||
126 | [heading Seq macros] | |
127 | ||
128 | The seq macros either work with a VMD seq or return A VMD seq. The seq macros are: | |
129 | ||
130 | [table:vpp_seq Seq macros | |
131 | [[Macro][Parameter][Return][Functionality][Header]] | |
132 | [ | |
133 | [BOOST_VMD_IS_VMD_SEQ] | |
134 | [sequence = a VMD sequence] | |
135 | [1 if the VMD sequence is a VMD seq, else 0] | |
136 | [Tests a sequence as a VMD seq. If the sequence is empty returns 1, otherwise returns the same as BOOST_VMD_IS_SEQ] | |
137 | [boost/vmd/seq/is_vmd_seq.hpp] | |
138 | ] | |
139 | [ | |
140 | [BOOST_VMD_SEQ_POP_BACK] | |
141 | [seq = a Boost PP seq] | |
142 | [A VMD seq] | |
143 | [Pops an element from the end of a seq. If the seq has a single element returns an empty seq, otherwise works exactly the same as BOOST_PP_SEQ_POP_BACK] | |
144 | [boost/vmd/seq/pop_back.hpp] | |
145 | ] | |
146 | [ | |
147 | [BOOST_VMD_SEQ_POP_FRONT] | |
148 | [seq = a Boost PP seq] | |
149 | [A VMD seq] | |
150 | [Pops an element from the beginning of a seq. If the seq has a single element returns an empty seq, otherwise works exactly the same as BOOST_PP_SEQ_POP_FRONT] | |
151 | [boost/vmd/seq/pop_front.hpp] | |
152 | ] | |
153 | [ | |
154 | [BOOST_VMD_SEQ_PUSH_BACK] | |
155 | [seq = a VMD seq, elem = element to push onto the end of the VMD seq] | |
156 | [A Boost PP seq] | |
157 | [Pushes an element onto the end of a VMD seq. If the VMD seq is empty the returned seq consists of that element, otherwise works exactly the same as BOOST_PP_SEQ_PUSH_BACK] | |
158 | [boost/vmd/seq/push_back.hpp] | |
159 | ] | |
160 | [ | |
161 | [BOOST_VMD_SEQ_PUSH_FRONT] | |
162 | [seq = a VMD seq, elem = element to push onto the beginning of the VMD seq] | |
163 | [A Boost PP seq] | |
164 | [Pushes an element onto the beginning of a VMD seq. If the VMD seq is empty the returned seq consists of that element, otherwise works exactly the same as BOOST_PP_SEQ_PUSH_FRONT] | |
165 | [boost/vmd/seq/push_front.hpp] | |
166 | ] | |
167 | [ | |
168 | [BOOST_VMD_SEQ_REMOVE] | |
169 | [seq = a Boost PP seq, i = index of element to remove] | |
170 | [A VMD seq] | |
171 | [Removes an element from a Boost PP seq. If the seq has a single element and the index to be removed is 0 returns an empty seq, otherwise works exactly the same as BOOST_PP_SEQ_REMOVE] | |
172 | [boost/vmd/seq/remove.hpp] | |
173 | ] | |
174 | [ | |
175 | [BOOST_VMD_SEQ_SIZE] | |
176 | [seq = a VMD seq] | |
177 | [The number of elements in the VMD seq] | |
178 | [Returns the number of elements in the VMD seq. If the seq is empty returns 0, otherwise works exactly the same as BOOST_PP_SEQ_SIZE] | |
179 | [boost/vmd/seq/size.hpp] | |
180 | ] | |
181 | [ | |
182 | [BOOST_VMD_SEQ_TO_ARRAY] | |
183 | [seq = a VMD seq] | |
184 | [A Boost PP array] | |
185 | [Converts a VMD seq to a Boost PP array. If the seq is empty returns an empty array whose form is '(0,())', otherwise works exactly the same as BOOST_PP_SEQ_TO_ARRAY] | |
186 | [boost/vmd/seq/to_array.hpp] | |
187 | ] | |
188 | [ | |
189 | [BOOST_VMD_SEQ_TO_LIST] | |
190 | [seq = a VMD seq] | |
191 | [A Boost PP list] | |
192 | [Converts a VMD seq to a Boost PP list. If the seq is empty returns an empty list whose form is 'BOOST_PP_NIL', otherwise works exactly the same as BOOST_PP_SEQ_TO_LIST] | |
193 | [boost/vmd/seq/to_list.hpp] | |
194 | ] | |
195 | [ | |
196 | [BOOST_VMD_SEQ_TO_TUPLE] | |
197 | [seq = a VMD seq] | |
198 | [A VMD tuple] | |
199 | [Converts a VMD seq to a VMD tuple. If the seq is empty returns an empty tuple, otherwise works exactly the same as BOOST_PP_SEQ_TO_TUPLE] | |
200 | [boost/vmd/seq/to_tuple.hpp] | |
201 | ] | |
202 | ] | |
203 | ||
204 | The difference between the seq macros and their equivalent ones in Boost PP is | |
205 | that working with a VMD seq or returning a VMD seq is valid with the seq macros | |
206 | but with the Boost PP equivalent macros working with an empty seq causes UB and | |
207 | returning an empty seq can never occur. | |
208 | ||
209 | You can include the seq macros either using their individual header files, | |
210 | the general 'boost/vmd/seq.hpp' header file for all seq macros, or the | |
211 | general header file 'boost/vmd/vmd.hpp' for all macros. | |
212 | ||
213 | [heading Tuple macros] | |
214 | ||
215 | The tuple macros either work with a VMD tuple or return a VMD tuple. The tuple macros are: | |
216 | ||
217 | [table:vpp_tuple Tuple macros | |
218 | [[Macro][Parameter][Return][Functionality][Header]] | |
219 | [ | |
220 | [BOOST_VMD_IS_VMD_TUPLE] | |
221 | [sequence = a VMD sequence] | |
222 | [1 if the VMD sequence is a VMD tuple, else 0] | |
223 | [Tests a sequence as a VMD tuple. If the sequence is empty returns 1, otherwise returns the same as BOOST_VMD_IS_TUPLE] | |
224 | [boost/vmd/tuple/is_vmd_tuple.hpp] | |
225 | ] | |
226 | [ | |
227 | [BOOST_VMD_TUPLE_POP_BACK] | |
228 | [tuple = a Boost PP tuple] | |
229 | [A VMD tuple] | |
230 | [Pops an element from the end of a tuple. If the tuple's size is 1 returns an empty tuple, otherwise works exactly the same as BOOST_PP_TUPLE_POP_BACK] | |
231 | [boost/vmd/tuple/pop_back.hpp] | |
232 | ] | |
233 | [ | |
234 | [BOOST_VMD_TUPLE_POP_FRONT] | |
235 | [tuple = a Boost PP tuple] | |
236 | [A VMD tuple] | |
237 | [Pops an element from the beginning of a tuple. If the tuple's size is 1 returns an empty tuple, otherwise works exactly the same as BOOST_PP_TUPLE_POP_FRONT] | |
238 | [boost/vmd/tuple/pop_front.hpp] | |
239 | ] | |
240 | [ | |
241 | [BOOST_VMD_TUPLE_PUSH_BACK] | |
242 | [tuple = a VMD tuple, elem = element to push onto the end of the VMD tuple] | |
243 | [A Boost PP tuple] | |
244 | [Pushes an element onto the end of a VMD tuple. If the VMD tuple is empty the returned tuple consists of that element, otherwise works exactly the same as BOOST_PP_TUPLE_PUSH_BACK] | |
245 | [boost/vmd/tuple/push_back.hpp] | |
246 | ] | |
247 | [ | |
248 | [BOOST_VMD_TUPLE_PUSH_FRONT] | |
249 | [tuple = a VMD tuple, elem = element to push onto the beginning of the VMD tuple] | |
250 | [A Boost PP tuple] | |
251 | [Pushes an element onto the beginning of a VMD tuple. If the VMD tuple is empty the returned tuple consists of that element, otherwise works exactly the same as BOOST_PP_TUPLE_PUSH_FRONT] | |
252 | [boost/vmd/tuple/push_front.hpp] | |
253 | ] | |
254 | [ | |
255 | [BOOST_VMD_TUPLE_REMOVE] | |
256 | [tuple = a Boost PP tuple, i = index of element to remove] | |
257 | [A VMD tuple] | |
258 | [Removes an element from a Boost PP tuple. If the tuple has a single element and the index to be removed is 0 returns an empty tuple, otherwise works exactly the same as BOOST_PP_TUPLE_REMOVE] | |
259 | [boost/vmd/tuple/remove.hpp] | |
260 | ] | |
261 | [ | |
262 | [BOOST_VMD_TUPLE_SIZE] | |
263 | [tuple = a VMD tuple] | |
264 | [The number of elements in the VMD tuple] | |
265 | [Returns the number of elements in the VMD tuple. If the tuple is empty returns 0, otherwise works exactly the same as BOOST_PP_TUPLE_SIZE] | |
266 | [boost/vmd/tuple/size.hpp] | |
267 | ] | |
268 | [ | |
269 | [BOOST_VMD_TUPLE_TO_ARRAY] | |
270 | [tuple = a VMD tuple] | |
271 | [A Boost PP array] | |
272 | [Converts a VMD tuple to a Boost PP array. If the tuple is empty returns an empty array whose form is '(0,())', otherwise works exactly the same as BOOST_PP_TUPLE_TO_ARRAY] | |
273 | [boost/vmd/tuple/to_array.hpp] | |
274 | ] | |
275 | [ | |
276 | [BOOST_VMD_TUPLE_TO_LIST] | |
277 | [tuple = a VMD tuple] | |
278 | [A Boost PP list] | |
279 | [Converts a VMD tuple to a Boost PP list. If the tuple is empty returns an empty list whose form is 'BOOST_PP_NIL', otherwise works exactly the same as BOOST_PP_TUPLE_TO_LIST] | |
280 | [boost/vmd/tuple/to_list.hpp] | |
281 | ] | |
282 | [ | |
283 | [BOOST_VMD_TUPLE_TO_SEQ] | |
284 | [tuple = a VMD tuple] | |
285 | [A VMD seq] | |
286 | [Converts a VMD tuple to a VMD seq. If the tuple is empty returns an empty seq, otherwise works exactly the same as BOOST_PP_TUPLE_TO_SEQ] | |
287 | [boost/vmd/tuple/to_seq.hpp] | |
288 | ] | |
289 | ] | |
290 | ||
291 | The difference between the tuple macros and their equivalent ones in Boost PP is | |
292 | that working with a VMD tuple or returning a VMD tuple is valid with the tuple macros | |
293 | but with the Boost PP equivalent macros working with an empty tuple causes UB and | |
294 | returning an empty tuple can never occur. | |
295 | ||
296 | You can include the tuple macros either using their individual header files, | |
297 | the general 'boost/vmd/tuple.hpp' header file for all tuple macros, or the | |
298 | general header file 'boost/vmd/vmd.hpp' for all macros. | |
299 | ||
300 | [heading Seq and tuple functionality] | |
301 | ||
302 | The set of macros for seq and tuple functionality which work with VMD seqs and | |
303 | VMD tuples are largely only a subset of the seq and tuple functionality in Boost PP. This reflects | |
304 | the fact that a number of macros in Boost PP for working with a seq or tuple make no | |
305 | sense when extended to work with a possible empty seq or empty tuple. For instance | |
306 | BOOST_PP_SEQ_FIRST_N could not mean anything when passed an empty | |
307 | seq and BOOST_PP_TUPLE_REM_CTOR could not mean anything when passed an empty tuple. | |
308 | Likewise for other Boost PP seq and tuple macros which do not have a VMD equivalent. | |
309 | ||
310 | The set of functionality in VMD for working with a possibly empty seq or empty tuple makes | |
311 | it possible to add or remove elements in a seq or tuple which could start out or | |
312 | end up empty, take the seq or tuple size even when the seq or tuple is empty, | |
313 | convert between arrays, lists, seqs, or tuples which could start out or end up | |
314 | empty, and test for a VMD seq or a VMD tuple. This functionality should allow macro | |
315 | programmers the ability to work with empty seqs and tuples while still using other | |
316 | Boost PP seq and tuple functuionality to work with non-empty seqs and tuples. The | |
317 | easiest way to do this is to use the VMD seq and VMD tuple equivalent functions | |
318 | when choosing between VMD and Boost PP, and use the Boost PP seq and tuple | |
319 | functionality otherwise. Just remember that Boost PP seq and tuple functionality | |
320 | can never work with empty seqs or empty tuples. | |
321 | ||
322 | [endsect] |