]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/vmd/doc/vmd_pp_data_types.qbk
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / vmd / doc / vmd_pp_data_types.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_pp_data_types VMD and Boost PP data types]
9
10 VMD is able to determine whether or not preprocessing input
11 is a given Boost PP data type. The VMD macros to do this are:
12
13 * BOOST_VMD_IS_ARRAY for an array
14 * BOOST_VMD_IS_LIST for a list
15 * BOOST_VMD_IS_SEQ for a seq
16 * BOOST_VMD_IS_TUPLE for a tuple
17
18 Each of these macros take a single parameter as input and
19 return 1 if the parameter is the appropriate data type and
20 0 if it is not.
21
22 [heading Syntax anomalies]
23
24 Both an array and a non-empty list are also a tuple. So if
25 one has:
26
27 #define ANARRAY (3,(a,b,c))
28 #define ALIST (a,(b,(c,BOOST_PP_NIL)))
29 #define ATUPLE (a,b,c)
30 #define ASEQ (a)(b)(c)
31
32 then
33
34 #include <boost/vmd/is_tuple.hpp>
35
36 BOOST_VMD_IS_TUPLE(ANARRAY) returns 1
37 BOOST_VMD_IS_TUPLE(ALIST) returns 1
38 BOOST_VMD_IS_TUPLE(ATUPLE) returns 1
39 BOOST_VMD_IS_TUPLE(ASEQ) returns 0
40
41 A list whose first element is the number 2 and whose second
42 element is not the end-of-list marker BOOST_PP_NIL is also
43 an array. So if one has:
44
45 #define ALIST (2,(3,BOOST_PP_NIL))
46 #define ALIST2 (2,(3,(4,BOOST_PP_NIL)))
47 #define ALIST3 (2,BOOST_PP_NIL)
48
49 #include <boost/vmd/is_array.hpp>
50 #include <boost/vmd/is_list.hpp>
51
52 BOOST_VMD_IS_LIST(ALIST) returns 1
53 BOOST_VMD_IS_LIST(ALIST2) returns 1
54 BOOST_VMD_IS_LIST(ALIST3) returns 1
55 BOOST_VMD_IS_ARRAY(ALIST) returns 1
56 BOOST_VMD_IS_ARRAY(ALIST2) returns 1
57 BOOST_VMD_IS_ARRAY(ALIST3) returns 0
58
59 A single element tuple is also a one element seq. So if one has:
60
61 #define ASE_TUPLE (a)
62
63 then
64
65 #include <boost/vmd/is_seq.hpp>
66 #include <boost/vmd/is_tuple.hpp>
67
68 BOOST_VMD_IS_TUPLE(ASE_TUPLE) returns 1
69 BOOST_VMD_IS_SEQ(ASE_TUPLE) returns 1
70
71 [heading Problem when testing an array]
72
73 The form of an array is a two element tuple, where the first
74 element is a number and the second element is a tuple. The number
75 specifies the size of the tuple. Since when using variadic macros
76 it is never necessary to specify the size of a tuple, an array is
77 largely obsolete. However VMD still supports it.
78
79 The problem when testing for an array is that if the first element
80 does not obey the constraint on testing for a number, you will get
81 UB.
82
83 #include <boost/vmd/is_array.hpp>
84 #include <boost/vmd/is_tuple.hpp>
85
86 #define A_TUPLE (&anything,(1,2))
87
88 BOOST_VMD_IS_ARRAY(A_TUPLE) will give UB due to the constraint
89 BOOST_VMD_IS_TUPLE(A_TUPLE) will return 1
90
91 When VMD attempts to parse for an array, as it does when the BOOST_VMD_IS_ARRAY
92 is used, if first looks to see if the syntax represents a tuple with two elements.
93 Next it looks to see if the second element itself is a tuple. Finally if it is
94 satisfied that the previous checks are valid it tests whether the first element
95 is a number or not. It is in this final test, that the first element is a valid
96 number, where the UB could occur as explained in the topic 'Numbers'.
97
98 [heading Problem when testing a list]
99
100 The form of a non-empty list is a two element tuple, where the first
101 element is the head of the list and can be anything and the
102 second element is itself a list or the end-of-list identifier
103 BOOST_PP_NIL.
104
105 The problem when testing for a list is that if the second element
106 does not obey the constraint on testing for an identifier, since BOOST_PP_NIL
107 is an identifier and is tested as such, you will get UB.
108
109 #include <boost/vmd/is_list.hpp>
110 #include <boost/vmd/is_tuple.hpp>
111
112 #define A_TUPLE (element,&anything)
113
114 BOOST_VMD_IS_LIST(A_TUPLE) will give UB due to the constraint
115 BOOST_VMD_IS_TUPLE(A_TUPLE) will return 1
116
117 The form of an empty list is the identifier BOOST_PP_NIL. Therefore:
118
119 #include <boost/vmd/is_identifier.hpp>
120 #include <boost/vmd/is_list.hpp>
121
122 #define A_BAD_EMPTY_LIST &BOOST_PP_NIL
123
124 BOOST_VMD_IS_LIST(A_BAD_EMPTY_LIST) will give UB due to the constraint
125 BOOST_VMD_IS_IDENTIFIER(A_BAD_EMPTY_LIST) will give UB due to the constraint
126
127 When VMD attempts to parse for a list, as it does when the BOOST_VMD_IS_LIST
128 is used, if first looks to see if the syntax represents a tuple with two elements.
129 If it is not a tuple with two elements it will check for the end-of-list.
130 If it is a tuple with two elements it looks to see if the second element is a list.
131 In both these paths it must always eventually check for the end-of-list notation
132 BOOST_PP_NIL, which is an identifier in VMD. It is in this final test, that the
133 end-of-list notation exists as a VMD identifier, where the UB
134 could occur as explained in the topic 'Identifiers'.
135
136 [heading Distinguishing a seq and a tuple]
137
138 As has previously been mentioned a single element tuple
139 is also a one element seq.
140
141 However, as will be discussed later in the documentation, when VMD has to
142 determine the type of such data, it always returns it as a tuple ( BOOST_VMD_TYPE_TUPLE ).
143
144 If our data consists of more than one consecutive tuple of a single
145 element the data is a seq:
146
147 #include <boost/vmd/is_seq.hpp>
148 #include <boost/vmd/is_tuple.hpp>
149
150 #define ST_DATA (somedata)(some_other_data)
151
152 BOOST_VMD_IS_SEQ(ST_DATA) will return 1
153 BOOST_VMD_IS_TUPLE(ST_DATA) will return 0
154
155 However if the data consists of a mixture we need to distinguish
156 how VMD parses the data. The rule is that VMD always parses a single
157 element tuple as a tuple unless it is followed by one or more single
158 element tuples, in which case it is a seq.
159
160 #define ST_DATA (somedata)(element1,element2)
161
162 VMD parses the above data as 2 consecutive tuples.
163 The first tuple is the single element tuple '(somedata)' and the second tuple
164 is the multi element tuple '(element1,element2)'.
165
166 #define ST_DATA (element1,element2)(somedata)
167
168 VMD parses the above data as 2 consecutive tuples.
169 The first tuple is the multi element tuple '(element1,element2)' and the second tuple
170 is the single element tuple '(somedata)'.
171
172 #define ST_DATA (somedata)(some_other_data)(element1,element2)
173
174 VMD parses the above data as a seq followed by a tuple.
175 The seq is '(somedata)(some_other_data)' and the tuple is
176 '(element1,element2)'.
177
178 [heading Empty Boost PP data types]
179
180 An array and a list can be empty.
181
182 An empty array has the form '(0,())', and is a perfectly valid array.
183
184 You can test for an empty array using the macro BOOST_VMD_IS_EMPTY_ARRAY.
185
186 #include <boost/vmd/is_array.hpp>
187 #include <boost/vmd/is_empty_array.hpp>
188
189 #define AN_ARRAY (1,(1))
190 #define AN_EMPTY_ARRAY (0,())
191
192 BOOST_VMD_IS_ARRAY(AN_ARRAY) will return 1
193 BOOST_VMD_IS_ARRAY(AN_EMPTY_ARRAY) will return 1
194
195 BOOST_VMD_IS_EMPTY_ARRAY(AN_EMPTY_ARRAY) will return 1
196 BOOST_VMD_IS_EMPTY_ARRAY() will return 0
197 BOOST_VMD_IS_EMPTY_ARRAY(AN_ARRAY) will return 0
198
199 An empty list has the form 'BOOST_PP_NIL', and is a perfectly valid list.
200
201 You can test for an empty list using the macro BOOST_VMD_IS_EMPTY_LIST.
202
203 #include <boost/vmd/is_empty_list.hpp>
204 #include <boost/vmd/is_list.hpp>
205
206 #define A_LIST (1,BOOST_PP_NIL)
207 #define AN_EMPTY_LIST BOOST_PP_NIL
208
209 BOOST_VMD_IS_LIST(A_LIST) will return 1
210 BOOST_VMD_IS_LIST(AN_EMPTY_LIST) will return 1
211
212 BOOST_VMD_IS_EMPTY_LIST(AN_EMPTY_LIST) will return 1
213 BOOST_VMD_IS_EMPTY_LIST() will return 0
214 BOOST_VMD_IS_EMPTY_LIST(A_LIST) will return 0
215
216 Neither seqs or tuples can be empty when using Boost PP. Because of this if you
217 convert from an empty array or list to a seq or tuple using
218 Boost PP macros to do so you will get undefined behavior.
219
220 The syntax '()', which is called an empty parenthesis, is neither a
221 zero-element seq or a tuple consisting of no elements. Rather it is
222 either a one-element seq whose content is emptiness or a single-element
223 tuple whose content is emptiness.
224
225 VMD supports the syntax of an empty parenthesis. You can test for it using
226 the macro BOOST_VMD_IS_PARENS_EMPTY.
227
228 #include <boost/vmd/is_parens_empty.hpp>
229 #include <boost/vmd/is_seq.hpp>
230 #include <boost/vmd/is_tuple.hpp>
231
232 #define EMPTY_PARENS ()
233 #define TUPLE (0)
234 #define SEQ (0)(1)
235
236 BOOST_VMD_IS_TUPLE(EMPTY_PARENS) will return 1
237 BOOST_VMD_IS_SEQ(EMPTY_PARENS) will return 1
238
239 BOOST_VMD_IS_PARENS_EMPTY(EMPTY_PARENS) will return 1
240 BOOST_VMD_IS_PARENS_EMPTY() will return 0
241 BOOST_VMD_IS_PARENS_EMPTY(TUPLE) will return 0
242 BOOST_VMD_IS_PARENS_EMPTY(SEQ) will return 0
243
244 The VC++8 compiler ( Visual Studio 2005 ), which is the oldest
245 VC++ version which VMD supports, has trouble working with the empty
246 parenthesis syntax. Therefore if you have to use VC++8 avoid its use,
247 otherwise you should be fine using it if you desire.
248
249 [heading Using a tuple instead of an array]
250
251 When using variadic macros, the fact that an array can be empty is its only
252 advantage over a tuple. Otherwise using a tuple is always easier since
253 the syntax is simpler; you never have to notate the tuple's size.
254
255 Since VMD fully supports passing and returning emptiness you could use a tuple
256 instead of an array in all situations and simply pass or return emptiness to
257 represent an "empty" tuple, and as an equivalent to an empty array.
258
259 This notion of using emptiness to represent an "empty" tuple can also be extended
260 to using emptiness to represent an "empty" seq. However functionality in Boost PP
261 will not recognize emptiness as an empty tuple or seq, nor can you work with emptiness
262 to represent an empty tuple or empty seq using the Boost PP functionality for a tuple
263 or a seq. For a solution to using emptiness to represent an "empty" tuple or an
264 "empty" seq VMD has functionality which will be explained when we look at our last
265 area of functionality in VMD, useful variadic macros not in Boost PP.
266
267 [heading Usage]
268
269 You can use the general header file:
270
271 #include <boost/vmd/vmd.hpp>
272
273 or you can use individual header files for each of these macros.
274 The individual header files are:
275
276 #include <boost/vmd/is_array.hpp> // for the BOOST_VMD_IS_ARRAY macro
277 #include <boost/vmd/is_list.hpp> // for the BOOST_VMD_IS_LIST macro
278 #include <boost/vmd/is_seq.hpp> // for the BOOST_VMD_IS_SEQ macro
279 #include <boost/vmd/is_tuple.hpp> // for the BOOST_VMD_IS_TUPLE macro.
280
281 #include <boost/vmd/is_empty_array.hpp> // for the BOOST_VMD_IS_EMPTY_ARRAY macro.
282 #include <boost/vmd/is_empty_list.hpp> // for the BOOST_VMD_IS_EMPTY_LIST macro.
283 #include <boost/vmd/is_parens_empty.hpp> // for the BOOST_VMD_IS_PARENS_EMPTY macro.
284
285 [endsect]