variadic_macros.html 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  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>