• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<html>
2  <head>
3    <meta  content="text/html; charset=windows-1252"  http-equiv="content-type">
4    <title>variadic_macros.html</title>
5    <link  rel="stylesheet"  type="text/css"  href="../styles.css">
6    <style>
7    u { font-weight: normal; text-decoration: none; }
8    </style>
9  </head>
10  <body>
11    <h4>Variadic Macros</h4>
12    <div> Variadic macros are supported by a number of compilers. They are
13      macros of the form: </div>
14    <div  class="code">
15      <pre>#define SOME_MACRO(ZeroOrMoreParameters,...) macro expansion possible specifying __VA_ARGS__</pre>
16    </div>
17    <div> The '...' in the parameter list represents the variadic data when the
18      macro is invoked and the __VA_ARGS__ in the expansion represents the
19      variadic data in the expansion of the macro. Variadic data is of the form
20      of 1 or more preprocessor tokens separated by commas.<br>
21      <br>
22      The '...' must be the last parameter in the macro definition and there may
23      be 0 or more non-variadic parameters preceding it.<br>
24      <br>
25      In the expansion of the macro __VA_ARGS__ may be specified 0 or more times
26      to represent the variadic data. The variadic data in the expansion is a
27      comma separated list of preprocessor tokens representing the variadic data
28      which the invoker of the macro enters as the last arguments to the macro.<br>
29    </div>
30    <h4>Example<u> - Creating and invoking a variadic macro.</u></h4>
31    <div  class="code">
32      <pre>#define INITIALIZE_INT_ARRAY(array_name,...) \ <br> static int array_name[] = { __VA_ARGS__ }; \ <br> /**/<br><br> INITIALIZE_INT_ARRAY(myname,45,789,33510,9346,2)</pre>
33    </div>
34    <u> <span  style="font-weight: bold;">Preprocessor
35        Library Support<br>
36      </span></u>
37    <div>The library offers support for variadic macros for those
38      compilers
39      which support the feature. The library can automatically detect whether
40      a compiler supports variadic macros and sets the macro
41      BOOST_PP_VARIADICS accordingly to 1 if the compiler supports variadic
42      macros or 0 if the compiler does not support variadic macros.<br>
43      <br>
44      The end-user can #define BOOST_PP_VARIADICS to 1 or 0 himself in a
45      translation unit, before including any preprocessor header files, to
46      prevent the library from attempting to detect whether the compiler
47      supports variadic macros. This has the effect of manually turning on or
48      off variadic macro support in the library. Of course if one manually
49      turns on variadic macro support in the library, and one's compiler does
50      not support variadic macros, functionality in the library which uses
51      variadic macros will fail with error messages from the compiler.<br>
52      <br>
53      When BOOST_PP_VARIADICS is 1, the library offers some extended
54      functionality
55      by using variadic macros, and also offers extended support for working
56      with variadic data.<br><br>
57      <a  name="vmvcquirk"></a>Visual C++ has a
58      few quirks related to variadic macros which require the end-user to code
59      slightly differently. When BOOST_PP_VARIADICS is 1 and Visual C++ is the
60      compiler BOOST_PP_VARIADICS_MSVC is 1, else when BOOST_PP_VARIADICS is 1
61      and Visual C++ is not the compiler BOOST_PP_VARIADICS_MSVC is 0. When
62      BOOST_PP_VARIADICS is 0 then BOOST_PP_VARIADICS_MSVC is not defined.
63      In this way the end-user, when using variadic macros, can test for the
64      presence of Visual C++ as the compiler and code accordingly.<br>
65      <br>
66      Support for working with variadic
67      data is largely centered on being able to convert variadic data to
68      other library data types, since the
69      functionality for working with those Boost preprocessor library data
70      types is much greater than that for working with variadic data directly.<br>
71    </div>
72    <a  name="VNotation"></a>
73    <h4>Notation For Variadic Macros<br>
74    </h4>
75    <div>In the documentation, headers which have variadic macros,
76      and
77      variadic macros themselves, have a notation of '(v)' appended to them.
78      For the variadic macros themselves this signifies that
79      BOOST_PP_VARIADICS must be 1 for those variadic macros to be usable.
80      For variadic macros which have a non-variadic equivalent, the
81      non-variadic equivalent will be used if BOOST_PP_VARIADICS is set to 0.
82    </div>
83    <h4>Extended Functionality Using Variadic Macros<br>
84    </h4>
85    <div>Some macros in the library offer extended
86      functionality through the use of variadic macros.<br>
87      <br>
88      The variadic macro version offers the same functionality
89      as the non-variadic version, but because of the ability of the variadic
90      parameters to encompass a variable number of arguments, it also offers
91      an enhanced syntax using the same macro name.<br>
92      <br>
93      The macros in the library which offer this enhanced functionality are
94      all
95      centered on <i>tuple</i> manipulation. With variadic
96      macros it is
97      possible to
98      manipulate tuples without having to know the size of the tuple. So
99      while the invoker can still specify the size when using tuple macro
100      functionality, there are variadic versions of each of the tuple macros,
101      with the exact same name as the non-variadic macro, where the size need
102      not be specified.<br>
103    </div>
104    <h4>Extended Support For Variadic Data</h4>
105    <div>The library offers extended support for working with
106      variadic data
107      which goes beyond the functionality offered by the C++ specification
108      for variadic macros. It does this through preprocessor programming and
109      by using some of the other functionality in the library itself. Header
110      and macro names
111      in the library which offer extended support for working with variadic
112      data, and need the compiler to support variadic macros, are marked with
113      a (v)<sup> </sup>to indicate a variadic macro.<br>
114      <br>
115      The form of the functionality which the library offers is centered on
116      two macros which work with variadic data itself, and a set of macros
117      which convert between variadic data and other library data
118      types.<br>
119      <br>
120      The two macros are BOOST_PP_VARIADIC_ELEM and BOOST_PP_VARIADIC_SIZE,
121      which respectively return a particular token of variadic data and the
122      number of tokens of variadic data.<br>
123      <br>
124      The macros for converting variadic data to the library's data types are
125      BOOST_PP_VARIADIC_TO_ARRAY, BOOST_PP_VARIADIC_TO_LIST,
126      BOOST_PP_VARIADIC_TO_SEQ, and BOOST_PP_VARIADIC_TO_TUPLE.<br>
127      <br>
128      All of these macros need compiler support for variadic data and only
129      exist if BOOST_PP_VARIADICS is 1. <br>
130      <br>
131      The remaining four macros, which convert from a library data type
132      to comma-separated preprocessor tokens, which is the form of
133      variadic data, do not need compiler support for variadic
134      macros. These functions are BOOST_PP_ARRAY_ENUM, BOOST_PP_LIST_ENUM,
135      BOOST_PP_SEQ_ENUM, and BOOST_PP_TUPLE_ENUM. However if one wishes to
136      use this variadic data reliably as arguments to other macros, one needs
137      variadic macro support.<br>
138    </div>
139    <h4>C++20 Support For Variadic Macros</h4>
140    <div>
141      In the C++20 specification there is a new construct which can be
142      used in the expansion of a variadic macro, called __VA_OPT__. This
143      construct when used in the expansion of a variadic macro is followed
144      by an opening paranthesis ('('), preprocessor data, and a closing
145      parenthesis ('}'). When the variadic data passed by the invocation
146      of a variadic macro is empty, this new construct expands to nothing.
147      When the variadic data passed by the invocation of a variadic macro
148      is not empty, this new construct expands to the preprocessor data
149      between its opening and closing parentheses.
150      <br><br>
151      This library offers support for this new C++20 construct by automatically
152      detecting whether this new construct is supported by the compiler's
153      preprocessor when using the library. The library macro which detects
154      support for the __VA_OPT__ construct is called BOOST_PP_VARIADIC_HAS_OPT.
155      This is a function-like macro which takes no parameters and returns
156      1 if the compiler is working in C++20 mode and supports the __VA_OPT__
157      construct, while otherwise it returns 0.
158      <br>
159    </div>
160    <u  style="font-weight: bold;"> Using a Tuple Instead of an Array<br>
161    </u>
162    <div>An array as a preprocessor data type is a two-element tuple where the
163      first element is the array size and the second element is a tuple which
164      constitutes the array data. Because a tuple knows its own size when the
165      compiler supports variadic macros, there is no reason to use the array preprocessor
166      data type as opposed to the tuple preprocessor data type; the tuple data
167      type now has all of the functionality which the array data type has and is
168      syntactically easier to use. With variadic macro support, which is now
169      officially part of the latest C++ standard, the preprocessor array data
170      type is essentially obsolete for conforming C++ compilers. Only if your
171      compiler does not support variadic macros is the preprocessor array data
172      type still useful.</div>
173    <u  style="font-weight: bold;">Using Variadic Data</u>
174    <div>Variadic data exists in the
175      form of comma-separated preprocessor tokens. This is the case whether
176      the variadic data comes from the __VA_ARGS__ of a variadic macro, from
177      the conversion of a library's data type to variadic data, or the
178      manual construction of comma-separated preprocessing tokens by the
179      programmer writing a macro.<br>
180      <br>
181      The easiest way to work with
182      variadic data internally is to convert it to a library data type.
183      Library data types, whether an <i>array</i>, <i>list</i>,
184      <i>sequence</i>,
185      or <i>tuple</i>, have a rich set of functionality for
186      manipulating
187      data whereas
188      variadic data functionality in the library only allows one to access
189      the variadic data as a whole or to access a single token of the
190      variadic data at a time.<br>
191      <br>
192      The user of the library still may
193      choose to pass variadic data back into internal macros rather than
194      convert it to other library data types. There is no problem passing
195      variadic data as a whole to variadic macros as the last parameter of
196      the macro. However: <br>
197      <br>
198      <span  style="font-weight: bold;">Attempting to pass
199        variadic data as a
200        whole directly into a non-variadic macro is not guaranteed to work and
201        may fail.<br>
202      </span><br>
203      This occurs because of a preprocessor weakness in a number
204      of compilers, currently most notably Visual C++. Even passing variadic
205      data as arguments to a non-variadic macro, when it is not represented
206      in
207      the form of� __VA_ARGS__, may fail with certain compilers.<br>
208      <br>
209      What follows are very simple examples, showing how variadic data can be
210      passed to a non-variadic macro.<br>
211      <br>
212      First an example of what NOT to do.<br>
213    </div>
214    <h4>Example<u> - Passing variadic data as a whole to a
215        non-variadic
216        macro. DO NOT DO.</u></h4>
217    <div  class="code">
218      <pre>#define MACRO_ARG_2(x,y) BOOST_PP_ADD(x,y)<br>#define VAR_MACRO(...) __VA_ARGS__<br><br>/* The following should not be done and is not guaranteed to work with compilers. */<br><br><span
219 style="font-weight: bold;"><span  style="font-family: monospace;"></span></span>int xx = MACRO_ARG_2(VAR_MACRO(2,3));</pre>
220    </div>
221    <div> There are two ways to pass variadic data to a non-variadic
222      macro.
223      The
224      first of these is to pass the individual tokens of the variadic data
225      separately to the non-variadic macro using the BOOST_PP_VARIADIC_ELEM
226      macro in the library.<br>
227    </div>
228    <h4>Example<u> - Passing individual variadic data tokens to
229        a
230        non-variadic macro.<br>
231      </u></h4>
232    <div  class="code">
233      <pre>#define MACRO_ARG_2(x,y) BOOST_PP_ADD(x,y)<br>#define VAR_MACRO(...) __VA_ARGS__<br><br>/* The following will work correctly */<br><br>int xx = MACRO_ARG_2<br> (<br> BOOST_PP_VARIADIC_ELEM(0,VAR_MACRO(2,3)),<br> BOOST_PP_VARIADIC_ELEM(1,VAR_MACRO(2,3))<br> );</pre>
234    </div>
235    <div>The second way is to use a macro in the library called
236      BOOST_PP_OVERLOAD.
237      This macro allows one to "overload" a variadic macro to non-variadic
238      macros of different numbers of parameters, using a common prefix.
239    </div>
240    <h4>Example<u> - Passing variadic data as a whole to
241        BOOST_PP_OVERLOAD
242        and on to a non-variadic macro.<br>
243      </u></h4>
244    <div  class="code">
245      <pre>#define MACRO_ARG_2(x,y) BOOST_PP_ADD(x,y)<br>#define VAR_MACRO(...) __VA_ARGS__<br><br>/* The following will work correctly */<br><br>int xx = BOOST_PP_OVERLOAD(MACRO_ARG_,VAR_MACRO(2,3))(VAR_MACRO(2,3));<br><br>/* For Visual C++ it is necessary to do this */<br><br>int xx = <br>BOOST_PP_CAT(BOOST_PP_OVERLOAD(MACRO_ARG_,VAR_MACRO(2,3))(VAR_MACRO(2,3)),BOOST_PP_EMPTY());</pre>
246    </div>
247    <br>
248    <div>Although these techniques will work when passing variadic
249      data to
250      non-variadic macros, it is much better and less problematical to
251      work internally with the existing library data types and to only use
252      variadic
253      macros as an interface for end-users when there is a need to have a
254      macro which takes a
255      variable number of parameters.<br>
256    </div>
257    <b>See</b> <b>Also</b><br>
258    <ul>
259      <li><a  href="../ref/variadics.html">BOOST_PP_VARIADICS</a></li>
260      <li><a  href="../headers/tuple.html">Tuple Macros</a><br>
261      </li>
262      <li><a  href="../headers/variadic.html">Variadic
263          Macros<br>
264        </a></li>
265      <li><a  href="../ref/array_enum.html">BOOST_PP_ARRAY_ENUM</a></li>
266      <li><a  href="../ref/list_enum_r.html">BOOST_PP_LIST_ENUM</a></li>
267      <li><a  href="../ref/seq_enum.html">BOOST_PP_SEQ_ENUM</a></li>
268      <li><a  href="../ref/tuple_enum.html">BOOST_PP_TUPLE_ENUM</a></li>
269      <li><a  href="../ref/overload.html">BOOST_PP_OVERLOAD</a></li>
270    </ul>
271    <hr  size="1">
272    <div  style="margin-left: 0px;"> <i>� Copyright
273        Edward Diener
274        2011,2013,2016</i> </div>
275    <div  style="margin-left: 0px;">
276      <p><small>Distributed under the Boost Software License,
277          Version 1.0.
278          (See accompanying file <a  href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a>
279          or copy at <a  href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</small></p>
280    </div>
281  </body>
282</html>