Brian Silverman | f27e085 | 2018-08-04 23:56:45 -0700 | [diff] [blame^] | 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 | <u style="font-weight: bold;"> Using a Tuple Instead of an Array<br> |
| 140 | </u> |
| 141 | <div>An array as a preprocessor data type is a two-element tuple where the |
| 142 | first element is the array size and the second element is a tuple which |
| 143 | constitutes the array data. Because a tuple knows its own size when the |
| 144 | compiler supports variadic macros, there is no reason to use the array preprocessor |
| 145 | data type as opposed to the tuple preprocessor data type; the tuple data |
| 146 | type now has all of the functionality which the array data type has and is |
| 147 | syntactically easier to use. With variadic macro support, which is now |
| 148 | officially part of the latest C++ standard, the preprocessor array data |
| 149 | type is essentially obsolete for conforming C++ compilers. Only if your |
| 150 | compiler does not support variadic macros is the preprocessor array data |
| 151 | type still useful.</div> |
| 152 | <u style="font-weight: bold;">Using Variadic Data</u> |
| 153 | <div>Variadic data exists in the |
| 154 | form of comma-separated preprocessor tokens. This is the case whether |
| 155 | the variadic data comes from the __VA_ARGS__ of a variadic macro, from |
| 156 | the conversion of a library's data type to variadic data, or the |
| 157 | manual construction of comma-separated preprocessing tokens by the |
| 158 | programmer writing a macro.<br> |
| 159 | <br> |
| 160 | The easiest way to work with |
| 161 | variadic data internally is to convert it to a library data type. |
| 162 | Library data types, whether an <i>array</i>, <i>list</i>, |
| 163 | <i>sequence</i>, |
| 164 | or <i>tuple</i>, have a rich set of functionality for |
| 165 | manipulating |
| 166 | data whereas |
| 167 | variadic data functionality in the library only allows one to access |
| 168 | the variadic data as a whole or to access a single token of the |
| 169 | variadic data at a time.<br> |
| 170 | <br> |
| 171 | The user of the library still may |
| 172 | choose to pass variadic data back into internal macros rather than |
| 173 | convert it to other library data types. There is no problem passing |
| 174 | variadic data as a whole to variadic macros as the last parameter of |
| 175 | the macro. However: <br> |
| 176 | <br> |
| 177 | <span style="font-weight: bold;">Attempting to pass |
| 178 | variadic data as a |
| 179 | whole directly into a non-variadic macro is not guaranteed to work and |
| 180 | may fail.<br> |
| 181 | </span><br> |
| 182 | This occurs because of a preprocessor weakness in a number |
| 183 | of compilers, currently most notably Visual C++. Even passing variadic |
| 184 | data as arguments to a non-variadic macro, when it is not represented |
| 185 | in |
| 186 | the form of __VA_ARGS__, may fail with certain compilers.<br> |
| 187 | <br> |
| 188 | What follows are very simple examples, showing how variadic data can be |
| 189 | passed to a non-variadic macro.<br> |
| 190 | <br> |
| 191 | First an example of what NOT to do.<br> |
| 192 | </div> |
| 193 | <h4>Example<u> - Passing variadic data as a whole to a |
| 194 | non-variadic |
| 195 | macro. DO NOT DO.</u></h4> |
| 196 | <div class="code"> |
| 197 | <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 |
| 198 | style="font-weight: bold;"><span style="font-family: monospace;"></span></span>int xx = MACRO_ARG_2(VAR_MACRO(2,3));</pre> |
| 199 | </div> |
| 200 | <div> There are two ways to pass variadic data to a non-variadic |
| 201 | macro. |
| 202 | The |
| 203 | first of these is to pass the individual tokens of the variadic data |
| 204 | separately to the non-variadic macro using the BOOST_PP_VARIADIC_ELEM |
| 205 | macro in the library.<br> |
| 206 | </div> |
| 207 | <h4>Example<u> - Passing individual variadic data tokens to |
| 208 | a |
| 209 | non-variadic macro.<br> |
| 210 | </u></h4> |
| 211 | <div class="code"> |
| 212 | <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> |
| 213 | </div> |
| 214 | <div>The second way is to use a macro in the library called |
| 215 | BOOST_PP_OVERLOAD. |
| 216 | This macro allows one to "overload" a variadic macro to non-variadic |
| 217 | macros of different numbers of parameters, using a common prefix. |
| 218 | </div> |
| 219 | <h4>Example<u> - Passing variadic data as a whole to |
| 220 | BOOST_PP_OVERLOAD |
| 221 | and on to a non-variadic macro.<br> |
| 222 | </u></h4> |
| 223 | <div class="code"> |
| 224 | <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> |
| 225 | </div> |
| 226 | <br> |
| 227 | <div>Although these techniques will work when passing variadic |
| 228 | data to |
| 229 | non-variadic macros, it is much better and less problematical to |
| 230 | work internally with the existing library data types and to only use |
| 231 | variadic |
| 232 | macros as an interface for end-users when there is a need to have a |
| 233 | macro which takes a |
| 234 | variable number of parameters.<br> |
| 235 | </div> |
| 236 | <b>See</b> <b>Also</b><br> |
| 237 | <ul> |
| 238 | <li><a href="../ref/variadics.html">BOOST_PP_VARIADICS</a></li> |
| 239 | <li><a href="../headers/tuple.html">Tuple Macros</a><br> |
| 240 | </li> |
| 241 | <li><a href="../headers/variadic.html">Variadic |
| 242 | Macros<br> |
| 243 | </a></li> |
| 244 | <li><a href="../ref/array_enum.html">BOOST_PP_ARRAY_ENUM</a></li> |
| 245 | <li><a href="../ref/list_enum_r.html">BOOST_PP_LIST_ENUM</a></li> |
| 246 | <li><a href="../ref/seq_enum.html">BOOST_PP_SEQ_ENUM</a></li> |
| 247 | <li><a href="../ref/tuple_enum.html">BOOST_PP_TUPLE_ENUM</a></li> |
| 248 | <li><a href="../ref/overload.html">BOOST_PP_OVERLOAD</a></li> |
| 249 | </ul> |
| 250 | <hr size="1"> |
| 251 | <div style="margin-left: 0px;"> <i>© Copyright |
| 252 | Edward Diener |
| 253 | 2011,2013,2016</i> </div> |
| 254 | <div style="margin-left: 0px;"> |
| 255 | <p><small>Distributed under the Boost Software License, |
| 256 | Version 1.0. |
| 257 | (See accompanying file <a href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> |
| 258 | or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</small></p> |
| 259 | </div> |
| 260 | |
| 261 | |
| 262 | </body></html> |