]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/vmd/doc/vmd_identity.qbk
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / vmd / doc / vmd_identity.qbk
CommitLineData
7c673cae
FG
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_identity Generating emptiness and identity]
9
10[heading Using BOOST_PP_EMPTY and BOOST_PP_IDENTITY]
11
12Boost PP Has a macro called BOOST_PP_EMPTY() which expands to nothing.
13
14Ordinarily this would not seem that useful, but the macro can be used
15in situations where one wants to return a specific value even though
16a further macro call syntax is required taking no parameters.
17This sort of usefulness occurs in Boost PP when there are two paths to take depending
18on the outcome of a BOOST_PP_IF or BOOST_PP_IIF logic. Here is an artificial example:
19
20 #include <boost/preprocessor/control/iif.hpp>
21 #include <boost/preprocessor/facilities/empty.hpp>
22
23 #define MACRO_CHOICE(parameter) \
24 BOOST_PP_IIF(parameter) \
25 ( \
26 MACRO_CALL_IF_PARAMETER_1, \
27 SOME_FIXED_VALUE BOOST_PP_EMPTY \
28 ) \
29 ()
30
31 #define MACRO_CALL_IF_PARAMETER_1() some_processing
32
33In the general logic above is: if parameter is 1 another
34macro is invoked, whereas if the parameter is 0 some
35fixed value is returned. The reason that this is useful
36is that one may not want to code the MACRO_CHOICE macro
37in this way:
38
39 #include <boost/preprocessor/control/iif.hpp>
40
41 #define MACRO_CHOICE(parameter) \
42 BOOST_PP_IIF(parameter) \
43 ( \
44 MACRO_CALL_IF_PARAMETER_1(), \
45 SOME_FIXED_VALUE \
46 )
47
48 #define MACRO_CALL_IF_PARAMETER_1() some_processing
49
50because it is inefficient. The invocation of MACRO_CALL_IF_PARAMETER_1 will still
51be generated even when 'parameter' is 0.
52
53This idiom of returning a fixed value through the use of BOOST_PP_EMPTY
54is so useful that Boost PP has an accompanying macro to BOOST_PP_EMPTY to
55work with it. This accompanying macro is BOOST_PP_IDENTITY(value)().
56Essentially BOOST_PP_IDENTITY returns its value when it is invoked.
57Again, like BOOST_PP_EMPTY, the final invocation must be done with no value.
58
59Our example from above, which originally used BOOST_PP_EMPTY to return
60a fixed value, is now:
61
62 #include <boost/preprocessor/control/iif.hpp>
63 #include <boost/preprocessor/facilities/identity.hpp>
64
65 #define MACRO_CHOICE(parameter) \
66 BOOST_PP_IIF(parameter) \
67 ( \
68 MACRO_CALL_IF_PARAMETER_1, \
69 BOOST_PP_IDENTITY(SOME_FIXED_VALUE) \
70 ) \
71 ()
72
73 #define MACRO_CALL_IF_PARAMETER_1() some_processing
74
75The macro BOOST_PP_IDENTITY is actually just:
76
77 #define BOOST_PP_IDENTITY(value) value BOOST_PP_EMPTY
78
79so you can see how it is essentially a shorthand for the common
80case originally shown at the top of returning a value through the
81use of BOOST_PP_EMPTY.
82
83[heading Using BOOST_VMD_EMPTY and BOOST_VMD_IDENTITY]
84
85The one problem when using BOOST_PP_EMPTY and BOOST_PP_IDENTITY
86is that the final invocation must be with no parameters. This is
87very limiting. If the final invocation must be with one or more parameters
88you cannot use BOOST_PP_EMPTY or BOOST_PP_IDENTITY. In other words,
89making a change to either of our two examples:
90
91 #include <boost/preprocessor/control/iif.hpp>
92 #include <boost/preprocessor/facilities/empty.hpp>
93
94 #define MACRO_CHOICE(parameter1,parameter2) \
95 BOOST_PP_IIF(parameter1) \
96 ( \
97 MACRO_CALL_IF_PARAMETER_1, \
98 SOME_FIXED_VALUE BOOST_PP_EMPTY \
99 ) \
100 (parameter2)
101
102 #define MACRO_CALL_IF_PARAMETER_1(parameter2) some_processing_using_a_parameter
103
104or
105
106 #include <boost/preprocessor/control/iif.hpp>
107 #include <boost/preprocessor/facilities/identity.hpp>
108
109 #define MACRO_CHOICE(parameter1,parameter2) \
110 BOOST_PP_IIF(parameter1) \
111 ( \
112 MACRO_CALL_IF_PARAMETER_1, \
113 BOOST_PP_IDENTITY(SOME_FIXED_VALUE) \
114 ) \
115 (parameter2)
116
117 #define MACRO_CALL_IF_PARAMETER_1(parameter2) some_processing_using_a_parameter
118
119will produce a preprocessing error since the final invocation to either
120BOOST_PP_EMPTY or BOOST_PP_IDENTITY can not be done with 1 or more parameters.
121
122It would be much more useful if the final invocation could be done with
123any number of parameters. This is where using variadic macros solves the problem.
124The BOOST_VMD_EMPTY and BOOST_VMD_IDENTITY macros have the exact same
125functionality as their Boost PP counterparts but the final invocation can
126be made with any number of parameters, and those parameters are just ignored
127when BOOST_VMD_EMPTY or BOOST_VMD_IDENTITY is the choice.
128
129Now for our two examples we can have:
130
131 #include <boost/preprocessor/control/iif.hpp>
132 #include <boost/vmd/empty.hpp>
133
134 #define MACRO_CHOICE(parameter1,parameter2) \
135 BOOST_PP_IIF(parameter1) \
136 ( \
137 MACRO_CALL_IF_PARAMETER_1, \
138 SOME_FIXED_VALUE BOOST_VMD_EMPTY \
139 ) \
140 (parameter2)
141
142 #define MACRO_CALL_IF_PARAMETER_1(parameter2) some_processing_using_parameters
143
144or
145
146 #include <boost/preprocessor/control/iif.hpp>
147 #include <boost/vmd/identity.hpp>
148
149 #define MACRO_CHOICE(parameter1,parameter2) \
150 BOOST_PP_IIF(parameter1) \
151 ( \
152 MACRO_CALL_IF_PARAMETER_1, \
153 BOOST_VMD_IDENTITY(SOME_FIXED_VALUE) \
154 ) \
155 (parameter2)
156
157 #define MACRO_CALL_IF_PARAMETER_1(parameter2) some_processing_using_parameters
158
159and our macros will compile without preprocessing errors and work as expected.
160Both BOOST_VMD_EMPTY and BOOST_VMD_IDENTITY will take any number of parameters
161in their invocation, which makes them useful for a final invocation no matter
162what is being passed.
163
164[heading Usage for BOOST_VMD_EMPTY and BOOST_VMD_IDENTITY]
165
166To use the BOOST_VMD_EMPTY macro either include the general header:
167
168 #include <boost/vmd/vmd.hpp>
169
170or include the specific header:
171
172 #include <boost/vmd/empty.hpp>
173
174To use the BOOST_VMD_IDENTITY macro either include the general header:
175
176 #include <boost/vmd/vmd.hpp>
177
178or include the specific header:
179
180 #include <boost/vmd/identity.hpp>
181
182[heading Using BOOST_VMD_EMPTY and BOOST_VMD_IDENTITY with VC++]
183
184Unfortunately the Visual C++ preprocessor has a problem when a macro
185expands to something followed by a variadic macro which expands to nothing.
186This is the case when using BOOST_VMD_EMPTY following some non-empty expansion,
187or the equivalent use of BOOST_VMD_IDENTITY. As strange as it sounds this VC++
188preprocessor problem is normally solved by concatenating the result using BOOST_PP_CAT
189with an empty value. But then again the many non-standard behaviors of VC++
190are difficult to understand or even track.
191
192In order to make this technique transparent when used with a C++ standard
193conforming preprocessor or VC++ non-standard preprocessor you can use the
194BOOST_VMD_IDENTITY_RESULT macro passing to it a single parameter which is a result
195returned from a macro which uses BOOST_VMD_IDENTITY ( or its equivalent
196'value BOOST_VMD_EMPTY' usage ).
197
198Given our MACRO_CHOICE example above, if you have another macro invoking MACRO_CHOICE
199simply enclose that invocation within BOOST_VMD_IDENTITY_RESULT. As in the very simple:
200
201 #include <boost/vmd/identity.hpp>
202
203 #define CALLING_MACRO_CHOICE(parameter1,parameter2) \
204 BOOST_VMD_IDENTITY_RESULT(MACRO_CHOICE(parameter1,parameter2))
205
206Alternatively you can change MACRO_CHOICE so that its implementation
207and usage is:
208
209 #include <boost/preprocessor/control/iif.hpp>
210 #include <boost/vmd/identity.hpp>
211
212 #define MACRO_CHOICE(parameter1,parameter2) \
213 BOOST_VMD_IDENTITY_RESULT \
214 ( \
215 BOOST_PP_IIF(parameter1) \
216 ( \
217 MACRO_CALL_IF_PARAMETER_1, \
218 BOOST_VMD_IDENTITY(SOME_FIXED_VALUE) \
219 ) \
220 (parameter2) \
221 )
222
223 #define CALLING_MACRO_CHOICE(parameter1,parameter2) \
224 MACRO_CHOICE(parameter1,parameter2)
225
226Using BOOST_VMD_EMPTY and BOOST_VMD_IDENTITY in this way will ensure they can be used
227without preprocessing problems with either VC++ or any C++ standard conforming preprocessor.
228
229[heading Usage for BOOST_VMD_IDENTITY_RESULT]
230
231The macro BOOST_VMD_IDENTITY_RESULT is in the same header file as BOOST_VMD_IDENTITY,
232so to use the BOOST_VMD_IDENTITY_RESULT macro either include the general header:
233
234 #include <boost/vmd/vmd.hpp>
235
236or include the specific header:
237
238 #include <boost/vmd/identity.hpp>
239
240[endsect]