<html> | |
<head> | |
<meta content="text/html; charset=windows-1252" http-equiv="content-type"> | |
<title>variadic_macros.html</title> | |
<link rel="stylesheet" type="text/css" href="../styles.css"> | |
<style> | |
u { font-weight: normal; text-decoration: none; } | |
</style> | |
</head> | |
<body> | |
<h4>Variadic Macros</h4> | |
<div> Variadic macros are supported by a number of compilers. They are | |
macros of the form: </div> | |
<div class="code"> | |
<pre>#define SOME_MACRO(ZeroOrMoreParameters,...) macro expansion possible specifying __VA_ARGS__</pre> | |
</div> | |
<div> The '...' in the parameter list represents the variadic data when the | |
macro is invoked and the __VA_ARGS__ in the expansion represents the | |
variadic data in the expansion of the macro. Variadic data is of the form | |
of 1 or more preprocessor tokens separated by commas.<br> | |
<br> | |
The '...' must be the last parameter in the macro definition and there may | |
be 0 or more non-variadic parameters preceding it.<br> | |
<br> | |
In the expansion of the macro __VA_ARGS__ may be specified 0 or more times | |
to represent the variadic data. The variadic data in the expansion is a | |
comma separated list of preprocessor tokens representing the variadic data | |
which the invoker of the macro enters as the last arguments to the macro.<br> | |
</div> | |
<h4>Example<u> - Creating and invoking a variadic macro.</u></h4> | |
<div class="code"> | |
<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> | |
</div> | |
<u> <span style="font-weight: bold;">Preprocessor | |
Library Support<br> | |
</span></u> | |
<div>The library offers support for variadic macros for those | |
compilers | |
which support the feature. The library can automatically detect whether | |
a compiler supports variadic macros and sets the macro | |
BOOST_PP_VARIADICS accordingly to 1 if the compiler supports variadic | |
macros or 0 if the compiler does not support variadic macros.<br> | |
<br> | |
The end-user can #define BOOST_PP_VARIADICS to 1 or 0 himself in a | |
translation unit, before including any preprocessor header files, to | |
prevent the library from attempting to detect whether the compiler | |
supports variadic macros. This has the effect of manually turning on or | |
off variadic macro support in the library. Of course if one manually | |
turns on variadic macro support in the library, and one's compiler does | |
not support variadic macros, functionality in the library which uses | |
variadic macros will fail with error messages from the compiler.<br> | |
<br> | |
When BOOST_PP_VARIADICS is 1, the library offers some extended | |
functionality | |
by using variadic macros, and also offers extended support for working | |
with variadic data.<br><br> | |
<a name="vmvcquirk"></a>Visual C++ has a | |
few quirks related to variadic macros which require the end-user to code | |
slightly differently. When BOOST_PP_VARIADICS is 1 and Visual C++ is the | |
compiler BOOST_PP_VARIADICS_MSVC is 1, else when BOOST_PP_VARIADICS is 1 | |
and Visual C++ is not the compiler BOOST_PP_VARIADICS_MSVC is 0. When | |
BOOST_PP_VARIADICS is 0 then BOOST_PP_VARIADICS_MSVC is not defined. | |
In this way the end-user, when using variadic macros, can test for the | |
presence of Visual C++ as the compiler and code accordingly.<br> | |
<br> | |
Support for working with variadic | |
data is largely centered on being able to convert variadic data to | |
other library data types, since the | |
functionality for working with those Boost preprocessor library data | |
types is much greater than that for working with variadic data directly.<br> | |
</div> | |
<a name="VNotation"></a> | |
<h4>Notation For Variadic Macros<br> | |
</h4> | |
<div>In the documentation, headers which have variadic macros, | |
and | |
variadic macros themselves, have a notation of '(v)' appended to them. | |
For the variadic macros themselves this signifies that | |
BOOST_PP_VARIADICS must be 1 for those variadic macros to be usable. | |
For variadic macros which have a non-variadic equivalent, the | |
non-variadic equivalent will be used if BOOST_PP_VARIADICS is set to 0. | |
</div> | |
<h4>Extended Functionality Using Variadic Macros<br> | |
</h4> | |
<div>Some macros in the library offer extended | |
functionality through the use of variadic macros.<br> | |
<br> | |
The variadic macro version offers the same functionality | |
as the non-variadic version, but because of the ability of the variadic | |
parameters to encompass a variable number of arguments, it also offers | |
an enhanced syntax using the same macro name.<br> | |
<br> | |
The macros in the library which offer this enhanced functionality are | |
all | |
centered on <i>tuple</i> manipulation. With variadic | |
macros it is | |
possible to | |
manipulate tuples without having to know the size of the tuple. So | |
while the invoker can still specify the size when using tuple macro | |
functionality, there are variadic versions of each of the tuple macros, | |
with the exact same name as the non-variadic macro, where the size need | |
not be specified.<br> | |
</div> | |
<h4>Extended Support For Variadic Data</h4> | |
<div>The library offers extended support for working with | |
variadic data | |
which goes beyond the functionality offered by the C++ specification | |
for variadic macros. It does this through preprocessor programming and | |
by using some of the other functionality in the library itself. Header | |
and macro names | |
in the library which offer extended support for working with variadic | |
data, and need the compiler to support variadic macros, are marked with | |
a (v)<sup> </sup>to indicate a variadic macro.<br> | |
<br> | |
The form of the functionality which the library offers is centered on | |
two macros which work with variadic data itself, and a set of macros | |
which convert between variadic data and other library data | |
types.<br> | |
<br> | |
The two macros are BOOST_PP_VARIADIC_ELEM and BOOST_PP_VARIADIC_SIZE, | |
which respectively return a particular token of variadic data and the | |
number of tokens of variadic data.<br> | |
<br> | |
The macros for converting variadic data to the library's data types are | |
BOOST_PP_VARIADIC_TO_ARRAY, BOOST_PP_VARIADIC_TO_LIST, | |
BOOST_PP_VARIADIC_TO_SEQ, and BOOST_PP_VARIADIC_TO_TUPLE.<br> | |
<br> | |
All of these macros need compiler support for variadic data and only | |
exist if BOOST_PP_VARIADICS is 1. <br> | |
<br> | |
The remaining four macros, which convert from a library data type | |
to comma-separated preprocessor tokens, which is the form of | |
variadic data, do not need compiler support for variadic | |
macros. These functions are BOOST_PP_ARRAY_ENUM, BOOST_PP_LIST_ENUM, | |
BOOST_PP_SEQ_ENUM, and BOOST_PP_TUPLE_ENUM. However if one wishes to | |
use this variadic data reliably as arguments to other macros, one needs | |
variadic macro support.<br> | |
</div> | |
<u style="font-weight: bold;"> Using a Tuple Instead of an Array<br> | |
</u> | |
<div>An array as a preprocessor data type is a two-element tuple where the | |
first element is the array size and the second element is a tuple which | |
constitutes the array data. Because a tuple knows its own size when the | |
compiler supports variadic macros, there is no reason to use the array preprocessor | |
data type as opposed to the tuple preprocessor data type; the tuple data | |
type now has all of the functionality which the array data type has and is | |
syntactically easier to use. With variadic macro support, which is now | |
officially part of the latest C++ standard, the preprocessor array data | |
type is essentially obsolete for conforming C++ compilers. Only if your | |
compiler does not support variadic macros is the preprocessor array data | |
type still useful.</div> | |
<u style="font-weight: bold;">Using Variadic Data</u> | |
<div>Variadic data exists in the | |
form of comma-separated preprocessor tokens. This is the case whether | |
the variadic data comes from the __VA_ARGS__ of a variadic macro, from | |
the conversion of a library's data type to variadic data, or the | |
manual construction of comma-separated preprocessing tokens by the | |
programmer writing a macro.<br> | |
<br> | |
The easiest way to work with | |
variadic data internally is to convert it to a library data type. | |
Library data types, whether an <i>array</i>, <i>list</i>, | |
<i>sequence</i>, | |
or <i>tuple</i>, have a rich set of functionality for | |
manipulating | |
data whereas | |
variadic data functionality in the library only allows one to access | |
the variadic data as a whole or to access a single token of the | |
variadic data at a time.<br> | |
<br> | |
The user of the library still may | |
choose to pass variadic data back into internal macros rather than | |
convert it to other library data types. There is no problem passing | |
variadic data as a whole to variadic macros as the last parameter of | |
the macro. However: <br> | |
<br> | |
<span style="font-weight: bold;">Attempting to pass | |
variadic data as a | |
whole directly into a non-variadic macro is not guaranteed to work and | |
may fail.<br> | |
</span><br> | |
This occurs because of a preprocessor weakness in a number | |
of compilers, currently most notably Visual C++. Even passing variadic | |
data as arguments to a non-variadic macro, when it is not represented | |
in | |
the form of __VA_ARGS__, may fail with certain compilers.<br> | |
<br> | |
What follows are very simple examples, showing how variadic data can be | |
passed to a non-variadic macro.<br> | |
<br> | |
First an example of what NOT to do.<br> | |
</div> | |
<h4>Example<u> - Passing variadic data as a whole to a | |
non-variadic | |
macro. DO NOT DO.</u></h4> | |
<div class="code"> | |
<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 | |
style="font-weight: bold;"><span style="font-family: monospace;"></span></span>int xx = MACRO_ARG_2(VAR_MACRO(2,3));</pre> | |
</div> | |
<div> There are two ways to pass variadic data to a non-variadic | |
macro. | |
The | |
first of these is to pass the individual tokens of the variadic data | |
separately to the non-variadic macro using the BOOST_PP_VARIADIC_ELEM | |
macro in the library.<br> | |
</div> | |
<h4>Example<u> - Passing individual variadic data tokens to | |
a | |
non-variadic macro.<br> | |
</u></h4> | |
<div class="code"> | |
<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> | |
</div> | |
<div>The second way is to use a macro in the library called | |
BOOST_PP_OVERLOAD. | |
This macro allows one to "overload" a variadic macro to non-variadic | |
macros of different numbers of parameters, using a common prefix. | |
</div> | |
<h4>Example<u> - Passing variadic data as a whole to | |
BOOST_PP_OVERLOAD | |
and on to a non-variadic macro.<br> | |
</u></h4> | |
<div class="code"> | |
<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> | |
</div> | |
<br> | |
<div>Although these techniques will work when passing variadic | |
data to | |
non-variadic macros, it is much better and less problematical to | |
work internally with the existing library data types and to only use | |
variadic | |
macros as an interface for end-users when there is a need to have a | |
macro which takes a | |
variable number of parameters.<br> | |
</div> | |
<b>See</b> <b>Also</b><br> | |
<ul> | |
<li><a href="../ref/variadics.html">BOOST_PP_VARIADICS</a></li> | |
<li><a href="../headers/tuple.html">Tuple Macros</a><br> | |
</li> | |
<li><a href="../headers/variadic.html">Variadic | |
Macros<br> | |
</a></li> | |
<li><a href="../ref/array_enum.html">BOOST_PP_ARRAY_ENUM</a></li> | |
<li><a href="../ref/list_enum_r.html">BOOST_PP_LIST_ENUM</a></li> | |
<li><a href="../ref/seq_enum.html">BOOST_PP_SEQ_ENUM</a></li> | |
<li><a href="../ref/tuple_enum.html">BOOST_PP_TUPLE_ENUM</a></li> | |
<li><a href="../ref/overload.html">BOOST_PP_OVERLOAD</a></li> | |
</ul> | |
<hr size="1"> | |
<div style="margin-left: 0px;"> <i>© Copyright | |
Edward Diener | |
2011,2013,2016</i> </div> | |
<div style="margin-left: 0px;"> | |
<p><small>Distributed under the Boost Software License, | |
Version 1.0. | |
(See accompanying file <a href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> | |
or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</small></p> | |
</div> | |
</body></html> |