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>