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).
8 [section:vmd_pp_data_types VMD and Boost PP data types]
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:
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
18 Each of these macros take a single parameter as input and
19 return 1 if the parameter is the appropriate data type and
22 [heading Syntax anomalies]
24 Both an array and a non-empty list are also a tuple. So if
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)
34 #include <boost/vmd/is_tuple.hpp>
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
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:
45 #define ALIST (2,(3,BOOST_PP_NIL))
46 #define ALIST2 (2,(3,(4,BOOST_PP_NIL)))
47 #define ALIST3 (2,BOOST_PP_NIL)
49 #include <boost/vmd/is_array.hpp>
50 #include <boost/vmd/is_list.hpp>
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
59 A single element tuple is also a one element seq. So if one has:
65 #include <boost/vmd/is_seq.hpp>
66 #include <boost/vmd/is_tuple.hpp>
68 BOOST_VMD_IS_TUPLE(ASE_TUPLE) returns 1
69 BOOST_VMD_IS_SEQ(ASE_TUPLE) returns 1
71 [heading Problem when testing an array]
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.
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
83 #include <boost/vmd/is_array.hpp>
84 #include <boost/vmd/is_tuple.hpp>
86 #define A_TUPLE (&anything,(1,2))
88 BOOST_VMD_IS_ARRAY(A_TUPLE) will give UB due to the constraint
89 BOOST_VMD_IS_TUPLE(A_TUPLE) will return 1
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'.
98 [heading Problem when testing a list]
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
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.
109 #include <boost/vmd/is_list.hpp>
110 #include <boost/vmd/is_tuple.hpp>
112 #define A_TUPLE (element,&anything)
114 BOOST_VMD_IS_LIST(A_TUPLE) will give UB due to the constraint
115 BOOST_VMD_IS_TUPLE(A_TUPLE) will return 1
117 The form of an empty list is the identifier BOOST_PP_NIL. Therefore:
119 #include <boost/vmd/is_identifier.hpp>
120 #include <boost/vmd/is_list.hpp>
122 #define A_BAD_EMPTY_LIST &BOOST_PP_NIL
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
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'.
136 [heading Distinguishing a seq and a tuple]
138 As has previously been mentioned a single element tuple
139 is also a one element seq.
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 ).
144 If our data consists of more than one consecutive tuple of a single
145 element the data is a seq:
147 #include <boost/vmd/is_seq.hpp>
148 #include <boost/vmd/is_tuple.hpp>
150 #define ST_DATA (somedata)(some_other_data)
152 BOOST_VMD_IS_SEQ(ST_DATA) will return 1
153 BOOST_VMD_IS_TUPLE(ST_DATA) will return 0
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.
160 #define ST_DATA (somedata)(element1,element2)
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)'.
166 #define ST_DATA (element1,element2)(somedata)
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)'.
172 #define ST_DATA (somedata)(some_other_data)(element1,element2)
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)'.
178 [heading Empty Boost PP data types]
180 An array and a list can be empty.
182 An empty array has the form '(0,())', and is a perfectly valid array.
184 You can test for an empty array using the macro BOOST_VMD_IS_EMPTY_ARRAY.
186 #include <boost/vmd/is_array.hpp>
187 #include <boost/vmd/is_empty_array.hpp>
189 #define AN_ARRAY (1,(1))
190 #define AN_EMPTY_ARRAY (0,())
192 BOOST_VMD_IS_ARRAY(AN_ARRAY) will return 1
193 BOOST_VMD_IS_ARRAY(AN_EMPTY_ARRAY) will return 1
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
199 An empty list has the form 'BOOST_PP_NIL', and is a perfectly valid list.
201 You can test for an empty list using the macro BOOST_VMD_IS_EMPTY_LIST.
203 #include <boost/vmd/is_empty_list.hpp>
204 #include <boost/vmd/is_list.hpp>
206 #define A_LIST (1,BOOST_PP_NIL)
207 #define AN_EMPTY_LIST BOOST_PP_NIL
209 BOOST_VMD_IS_LIST(A_LIST) will return 1
210 BOOST_VMD_IS_LIST(AN_EMPTY_LIST) will return 1
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
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.
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.
225 VMD supports the syntax of an empty parenthesis. You can test for it using
226 the macro BOOST_VMD_IS_PARENS_EMPTY.
228 #include <boost/vmd/is_parens_empty.hpp>
229 #include <boost/vmd/is_seq.hpp>
230 #include <boost/vmd/is_tuple.hpp>
232 #define EMPTY_PARENS ()
236 BOOST_VMD_IS_TUPLE(EMPTY_PARENS) will return 1
237 BOOST_VMD_IS_SEQ(EMPTY_PARENS) will return 1
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
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.
249 [heading Using a tuple instead of an array]
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.
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.
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.
269 You can use the general header file:
271 #include <boost/vmd/vmd.hpp>
273 or you can use individual header files for each of these macros.
274 The individual header files are:
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.
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.