• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_whyhow Why and how to use]
9
10The VMD library provides the ability to create a macro which takes
11different types of parameters and can therefore generate different output
12depending on the parameter types as well as their values.
13
14This is equivalent to the way that overloaded
15functions provide the ability for a singularly named function
16to provide different functionality depending on the parameter
17types.
18
19In the case of macros, where more than one macro of the same
20name but different macro expansion is not allowed, a single macro name
21can create different expansions.
22
23As a simple example:
24
25 #include <boost/preprocessor/control/iif.hpp>
26 #include <boost/vmd/is_seq.hpp>
27 #include <boost/vmd/is_tuple.hpp>
28
29 #define AMACRO(param)                 \
30   BOOST_PP_IIF                        \
31     (                                 \
32     BOOST_VMD_IS_SEQ(param),          \
33     Seq,                              \
34     BOOST_PP_IIF                      \
35       (                               \
36       BOOST_VMD_IS_TUPLE(param),      \
37       Tuple,                          \
38       Unknown                         \
39       )                               \
40     )
41
42If the param passed is a seq the output of
43the macro is 'Seq'. If the param passed is
44a tuple the output of the macro is 'Tuple'.
45Otherwise the output of the macro is 'Unknown'.
46
47Obviously much more complicated cases can be created
48in which the types and values of various parameters
49are parsed in order to produce variable macro output
50depending on the input. Using variadic macros,
51macros with variable numbers and types of arguments
52give the macro programmer even greater freedom to
53design macros with flexibility.
54
55Another feature of the VMD library is the ability to parse
56identifiers. A system of registering identifiers which VMD
57can recognize has been created. Once an identifier is registered
58VMD can recognize it as part of macro input as an identifier and
59return the identifier. Furthermore VMD can compare identifiers
60for equality or inequality once an identifier has been pre-detected
61using VMD's system for pre-detecting identifiers.
62
63As another simple example:
64
65 #include <boost/preprocessor/control/iif.hpp>
66 #include <boost/vmd/is_identifier.hpp>
67
68 #define BOOST_VMD_REGISTER_NAME (NAME)
69 #define BOOST_VMD_REGISTER_ADDRESS (ADDRESS)
70
71 #define AMACRO1(param)              \
72   BOOST_PP_IIF                      \
73     (                               \
74     BOOST_VMD_IS_IDENTIFIER(param), \
75     AMACRO1_IDENTIFIER,             \
76     AMACRO1_NO_IDENTIFIER           \
77     )                               \
78   (param)
79
80 #define AMACRO1_IDENTIFIER(param) AMACRO1_ ## param
81 #define AMACRO1_NO_IDENTIFIER(param) Parameter is not an identifier
82 #define AMACRO1_NAME Identifier is a NAME
83 #define AMACRO1_ADDRESS Identifier is an ADDRESS
84
85Here we use VMD's identifier registration system to determine and
86handle a particular identifier we may be expecting as a macro parameter.
87If the input to 'AMACRO1' is 'NAME' the output is 'Identifier is a NAME'.
88If the input to 'AMACRO1' is 'ADDRESS' the output is 'Identifier is an ADDRESS'.
89Otherwise the output is 'Parameter is not an identifier'.
90
91Identifier pre-detection makes things clearer, allowing us to
92detect within VMD whether macro input matches a particular identifier.
93Using the same setup as our previous example, but with identifier pre-detection:
94
95 #include <boost/preprocessor/control/iif.hpp>
96 #include <boost/vmd/is_identifier.hpp>
97
98 #define BOOST_VMD_REGISTER_NAME (NAME)
99 #define BOOST_VMD_DETECT_NAME_NAME
100
101 #define BOOST_VMD_REGISTER_ADDRESS (ADDRESS)
102 #define BOOST_VMD_DETECT_ADDRESS_ADDRESS
103
104 #define AMACRO2(param)                        \
105   BOOST_PP_IIF                                \
106     (                                         \
107     BOOST_VMD_IS_IDENTIFIER(param,NAME),      \
108     AMACRO2_NAME,                             \
109     BOOST_PP_IIF                              \
110       (                                       \
111       BOOST_VMD_IS_IDENTIFIER(param,ADDRESS), \
112       AMACRO2_ADDRESS,                        \
113       AMACRO2_NO_IDENTIFIER                   \
114       )                                       \
115     )                                         \
116   (param)
117
118 #define AMACRO2_NO_IDENTIFIER(param) Parameter is not a NAME or ADDRESS identifier
119 #define AMACRO2_NAME(param) Identifier is a NAME
120 #define AMACRO2_ADDRESS(param) Identifier is an ADDRESS
121
122If the input to 'AMACRO2' is 'NAME' the output is 'Identifier is a NAME'.
123If the input to 'AMACRO2' is 'ADDRESS' the output is 'Identifier is an ADDRESS'.
124Otherwise the output is 'Parameter is not a NAME or ADDRESS identifier'.
125
126The VMD library also has 2 different subtypes of identifiers which can always be
127recognized. The first are numbers, equivalent to the number in Boost PP, numeric
128values with a range of 0-256. The second are v-types, which are identifiers starting
129with BOOST_VMD_TYPE_ followed by a name for the type of data. As an example, the v-type
130of a Boost PP tuple is BOOST_VMD_TYPE_TUPLE and the v-type of a v-type itself is
131BOOST_VMD_TYPE_TYPE. All data types have their own v-type identifier; types are
132recognized by the VMD macros and may be passed as input data just like any other of
133the types of data VMD recognizes.
134
135The VMD identifier system even has a way, to be explained later, for the end-user to
136create his own subtype identifiers.
137
138Another reason to use VMD is that VMD understands 'sequences' of the VMD data types. You
139can have a sequence of data types and VMD can convert the sequence to any of the Boost
140PP data types, or access any individual data type in a sequence.
141
142 #include <boost/vmd/elem.hpp>
143 #include <boost/vmd/to_tuple.hpp>
144
145 #define BOOST_VMD_REGISTER_NAME (NAME)
146 #define ASEQUENCE (1,2) NAME 147 BOOST_VMD_TYPE_NUMBER (a)(b)
147
148 BOOST_VMD_TO_TUPLE(ASEQUENCE)
149 BOOST_VMD_ELEM(2,ASEQUENCE)
150
151Our first expansion `BOOST_VMD_TO_TUPLE(ASEQUENCE)` returns the tuple:
152
153 ((1,2),NAME,147,BOOST_VMD_TYPE_NUMBER,(a)(b))
154
155Our second expansion `BOOST_VMD_ELEM(2,ASEQUENCE)` returns the sequence element:
156
157 147
158
159Sequences give the macro programmer the ability to accept input
160data from the user which may more closely mimic C++ constructs.
161
162Another reason to use VMD is that VMD understands data types.
163Besides specifically asking if a particular input is a particular
164data type, you can use the macro BOOST_VMD_GET_TYPE to retrieve
165the type of any VMD data.
166
167 #include <boost/vmd/get_type.hpp>
168
169 BOOST_VMD_GET_TYPE((1,2)) // expands to BOOST_VMD_TYPE_TUPLE
170 BOOST_VMD_GET_TYPE(235)   // expands to BOOST_VMD_TYPE_NUMBER
171
172etc.
173
174There is still much more of VMD functionality but hopefully this brief
175introduction of what VMD can do will interest you so that you will read on
176to understand VMD's functionality for the macro programmer.
177
178[endsect]