[DEV] add v1.66.0

This commit is contained in:
2018-01-12 21:47:58 +01:00
parent 87059bb1af
commit a97e9ae7d4
49032 changed files with 7668950 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Acknowledgements</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="prev" href="vmd_history.html" title="History">
<link rel="next" href="../index/s24.html" title="Index">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_history.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../index/s24.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="variadic_macro_data.vmd_ack"></a><a class="link" href="vmd_ack.html" title="Acknowledgements">Acknowledgements</a>
</h2></div></div></div>
<p>
First and foremost I would like to thank Paul Mensonides for providing advice,
explanation and code for working with variadic macros and macros in general.
Secondly I would like to thank Steve Watanabe for his help, code, and explanations.
Finally I have to acknowledge that this library is an amalgam of already known
techniques for dealing with variadic macros themselves, among which are techniques
published online by Paul Mensonides. I have added design and some cleverness
in creating the library but I could not have done it without the previous knowledge
of others.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_history.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../index/s24.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,61 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Compilers</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="prev" href="vmd_design.html" title="Design">
<link rel="next" href="vmd_history.html" title="History">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_design.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_history.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="variadic_macro_data.vmd_compilers"></a><a class="link" href="vmd_compilers.html" title="Compilers">Compilers</a>
</h2></div></div></div>
<p>
On Windows I have tested this library using gcc/MingW, VC++, and clang targeting
gcc. The compilers tested are gcc 4.3.0, 4.4.0, 4.5.0-1, 4.5.2-1, 4.6.0, 4.6.1,
4.6.2, 4.7.0, 4.7.2, 4.8.1, 4.8.2, 4.8.3, 4.8.4, 4.8.5, 4.9.0, 4.9.1, 4.9.2,
4.9.3, 5.1.0, 5.2.0, VC++ 8.0, 9.0, 10.0, 11.0, 12.0, 14.0. and clang 3.4,
3.5, 3.6, 3.7, and the latest clang build from source.
</p>
<p>
On Linux I have tested this library using gcc 4.4.7, 4.6.4, 4.7.3, 4.8.2, 4.8.3,
4.9.1, clang 3.3, 3.4, 3.5, and the latest clang build from source, and Intel
C++ 12.1. 13.0, 14.0, 15.0, 16.0.
</p>
<p>
For VC++ 8.0 the BOOST_VMD_IS_EMPTY and BOOST_VMD_ASSERT_IS_EMPTY macros take
a single parameter rather than variadic data because this version of VC++ does
not accept variadic data which may be empty.
</p>
<p>
The compilers supported are those which are deemed to offer C99/C++11 variadic
macro support for Boost PP as represented by the BOOST_PP_VARIADICS macro.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_design.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_history.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,434 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Version 1.7 to 1.8 conversion</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="prev" href="vmd_vc_isms.html" title="Visual C++ gotchas in VMD">
<link rel="next" href="vmd_examples.html" title="Examples using VMD functionality">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_vc_isms.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_examples.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="variadic_macro_data.vmd_conv"></a><a class="link" href="vmd_conv.html" title="Version 1.7 to 1.8 conversion">Version 1.7 to 1.8 conversion</a>
</h2></div></div></div>
<p>
Since the current version of VMD has been drastically changed to make it easier
to use VMD functionality this section details equivalent functionality for
previous version 1.7 VMD macros.
</p>
<p>
The changes in functionality involve the parsing of sequences. The equivalent
to all the V1.7 functionality, which looks for various data types at the beginning
of a sequence, is encompassed by the V1.8 macro BOOST_VMD_ELEM(0,sequence,...),
where '0' is the first sequence element and 'sequence' is the sequence, with
its optional parameters.
</p>
<h4>
<a name="variadic_macro_data.vmd_conv.h0"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_conv.identifier"></a></span><a class="link" href="vmd_conv.html#variadic_macro_data.vmd_conv.identifier">Identifier</a>
</h4>
<p>
V1.7
</p>
<p>
BOOST_VMD_IDENTIFIER(sequence,keys,...) looked for an identifier at the beginning
of a sequence and returned a 2-element tuple, where the first element is the
matching index starting with 1, or 0 if no identifier is found, and the second
tuple element is the rest of the sequence or emptiness if no identifier is
found.
</p>
<p>
V1.8 equivalent
</p>
<p>
BOOST_VMD_ELEM(0,sequence,(identifiers),BOOST_VMD_TYPE_IDENTIFIER,BOOST_VMD_RETURN_AFTER,BOOST_VMD_RETURN_INDEX)
returns a 3-element tuple where the identifier found is the first tuple element,
the rest of the sequence is the second tuple element, and the matching index,
starting with 0, is the 3rd tuple element. If no identifier is found all elements
of the returned tuple are empty.
</p>
<p>
V1.7
</p>
<p>
BOOST_VMD_BEGIN_IDENTIFIER(sequence,keys,...) looked for an identifier at the
beginning of a sequence and returned the matching index starting with 1, or
0 if no identifier is found.
</p>
<p>
V1.8 equivalent
</p>
<p>
BOOST_VMD_ELEM(0,sequence,(identifiers),BOOST_VMD_TYPE_IDENTIFIER,BOOST_VMD_RETURN_INDEX)
returns a 2-element tuple where the identifier found is the first tuple element
and the matching index, starting with 0, is the 2nd tuple element. If no identifier
is found both elements of the returned tuple are empty.
</p>
<p>
V1.7
</p>
<p>
BOOST_VMD_AFTER_IDENTIFIER(sequence,keys,...) looked for an identifier at the
beginning of a sequence and returned the rest of the sequence or emptiness
if no identifier is found.
</p>
<p>
V1.8 equivalent
</p>
<p>
BOOST_VMD_ELEM(0,sequence,(identifiers),BOOST_VMD_TYPE_IDENTIFIER,BOOST_VMD_RETURN_ONLY_AFTER)
is the exact equivalent.
</p>
<p>
V1.7
</p>
<p>
BOOST_VMD_IS_BEGIN_IDENTIFIER(sequence,keys,...) returns 1 if input begins
with an identifier, else 0 if it does not.
</p>
<p>
V1.8 equivalent
</p>
<p>
BOOST_VMD_ELEM(0,sequence,(identifiers),BOOST_VMD_TYPE_IDENTIFIER) returns
the identifier found, otherwise emptiness if not found. You can use BOOST_PP_COMPL(BOOST_VMD_IS_EMPTY(BOOST_VMD_ELEM(0,sequence,identifiers,BOOST_VMD_TYPE_IDENTIFIER)))
as the exact equivalent.
</p>
<h4>
<a name="variadic_macro_data.vmd_conv.h1"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_conv.number"></a></span><a class="link" href="vmd_conv.html#variadic_macro_data.vmd_conv.number">Number</a>
</h4>
<p>
V1.7
</p>
<p>
BOOST_VMD_NUMBER(sequence,...) looked for a number at the beginning of a sequence
and returned a 2-element tuple, where the first element is the number and the
second tuple element is the rest of the sequence. If no number is found both
tuple elements are empty.
</p>
<p>
V1.8 equivalent
</p>
<p>
BOOST_VMD_ELEM(0,sequence,BOOST_VMD_TYPE_NUMBER,BOOST_VMD_RETURN_AFTER) is
the exact equivalent.
</p>
<p>
V1.7
</p>
<p>
BOOST_VMD_BEGIN_NUMBER(sequence,...) looked for a number at the beginning of
a sequence and returned the number if found or emptiness if no number is found.
</p>
<p>
V1.8 equivalent
</p>
<p>
BOOST_VMD_ELEM(0,sequence,BOOST_VMD_TYPE_NUMBER) is the exact equivalent.
</p>
<p>
V1.7
</p>
<p>
BOOST_VMD_AFTER_NUMBER(sequence,...) looked for a number at the beginning of
a sequence and returned the rest of the sequence or emptiness if no number
is found.
</p>
<p>
V1.8 equivalent
</p>
<p>
BOOST_VMD_ELEM(0,sequence,BOOST_VMD_TYPE_NUMBER,BOOST_VMD_RETURN_ONLY_AFTER)
is the exact equivalent.
</p>
<p>
V1.7
</p>
<p>
BOOST_VMD_IS_BEGIN_NUMBER(sequence,...) returns 1 if input begins with a number,
else 0 if it does not.
</p>
<p>
V1.8 equivalent
</p>
<p>
BOOST_VMD_ELEM(0,sequence,BOOST_VMD_TYPE_NUMBER) returns the number found,
otherwise emptiness if not found. You can use BOOST_PP_COMPL(BOOST_VMD_IS_EMPTY(BOOST_VMD_ELEM(0,sequence,BOOST_VMD_TYPE_NUMBER)))
as the exact equivalent.
</p>
<h4>
<a name="variadic_macro_data.vmd_conv.h2"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_conv.array"></a></span><a class="link" href="vmd_conv.html#variadic_macro_data.vmd_conv.array">Array</a>
</h4>
<p>
V1.7
</p>
<p>
BOOST_VMD_ARRAY(sequence) looked for an array at the beginning of a sequence
and returned a 2-element tuple, where the first element is the array and the
second tuple element is the rest of the sequence. If no array is found both
tuple elements are empty.
</p>
<p>
V1.8 equivalent
</p>
<p>
BOOST_VMD_ELEM(0,sequence,BOOST_VMD_TYPE_ARRAY,BOOST_VMD_RETURN_AFTER) is the
exact equivalent.
</p>
<p>
V1.7
</p>
<p>
BOOST_VMD_BEGIN_ARRAY(sequence) looked for an array at the beginning of a sequence
and returned the array if found or emptiness if no array is found.
</p>
<p>
V1.8 equivalent
</p>
<p>
BOOST_VMD_ELEM(0,sequence,BOOST_VMD_TYPE_ARRAY) is the exact equivalent.
</p>
<p>
V1.7
</p>
<p>
BOOST_VMD_AFTER_ARRAY(sequence) looked for an array at the beginning of a sequence
and returned the rest of the sequence or emptiness if no array is found.
</p>
<p>
V1.8 equivalent
</p>
<p>
BOOST_VMD_ELEM(0,sequence,BOOST_VMD_TYPE_ARRAY,BOOST_VMD_RETURN_ONLY_AFTER)
is the exact equivalent.
</p>
<p>
V1.7
</p>
<p>
BOOST_VMD_IS_BEGIN_ARRAY(sequence,...) returns 1 if input begins with an array,
else 0 if it does not.
</p>
<p>
V1.8 equivalent
</p>
<p>
BOOST_VMD_ELEM(0,sequence,BOOST_VMD_TYPE_ARRAY) returns the array found, otherwise
emptiness if not found. You can use BOOST_PP_COMPL(BOOST_VMD_IS_EMPTY(BOOST_VMD_ELEM(0,sequence,BOOST_VMD_TYPE_ARRAY)))
as the exact equivalent.
</p>
<h4>
<a name="variadic_macro_data.vmd_conv.h3"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_conv.list"></a></span><a class="link" href="vmd_conv.html#variadic_macro_data.vmd_conv.list">List</a>
</h4>
<p>
V1.7
</p>
<p>
BOOST_VMD_LIST(sequence) looked for an list at the beginning of a sequence
and returned a 2-element tuple, where the first element is the list and the
second tuple element is the rest of the sequence. If no list is found both
tuple elements are empty.
</p>
<p>
V1.8 equivalent
</p>
<p>
BOOST_VMD_ELEM(0,sequence,BOOST_VMD_TYPE_LIST,BOOST_VMD_RETURN_AFTER) is the
exact equivalent.
</p>
<p>
V1.7
</p>
<p>
BOOST_VMD_BEGIN_LIST(sequence) looked for a list at the beginning of a sequence
and returned the list if found or emptiness if no list is found.
</p>
<p>
V1.8 equivalent
</p>
<p>
BOOST_VMD_ELEM(0,sequence,BOOST_VMD_TYPE_LIST) is the exact equivalent.
</p>
<p>
V1.7
</p>
<p>
BOOST_VMD_AFTER_LIST(sequence) looked for an list at the beginning of a sequence
and returned the rest of the sequence or emptiness if no list is found.
</p>
<p>
V1.8 equivalent
</p>
<p>
BOOST_VMD_ELEM(0,sequence,BOOST_VMD_TYPE_LIST,BOOST_VMD_RETURN_ONLY_AFTER)
is the exact equivalent.
</p>
<p>
V1.7
</p>
<p>
BOOST_VMD_IS_BEGIN_LIST(sequence,...) returns 1 if input begins with an list,
else 0 if it does not.
</p>
<p>
V1.8 equivalent
</p>
<p>
BOOST_VMD_ELEM(0,sequence,BOOST_VMD_TYPE_LIST) returns the list found, otherwise
emptiness if not found. You can use BOOST_PP_COMPL(BOOST_VMD_IS_EMPTY(BOOST_VMD_ELEM(0,sequence,BOOST_VMD_TYPE_LIST)))
as the exact equivalent.
</p>
<h4>
<a name="variadic_macro_data.vmd_conv.h4"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_conv.seq"></a></span><a class="link" href="vmd_conv.html#variadic_macro_data.vmd_conv.seq">Seq</a>
</h4>
<p>
V1.7
</p>
<p>
BOOST_VMD_SEQ(sequence) looked for a seq at the beginning of a sequence and
returned a 2-element tuple, where the first element is the seq and the second
tuple element is the rest of the sequence. If no seq is found both tuple elements
are empty.
</p>
<p>
V1.8 equivalent
</p>
<p>
BOOST_VMD_ELEM(0,sequence,BOOST_VMD_TYPE_SEQ,BOOST_VMD_RETURN_AFTER) is the
exact equivalent.
</p>
<p>
V1.7
</p>
<p>
BOOST_VMD_BEGIN_SEQ(sequence) looked for a seq at the beginning of a sequence
and returned the seq if found or emptiness if no seq is found.
</p>
<p>
V1.8 equivalent
</p>
<p>
BOOST_VMD_ELEM(0,sequence,BOOST_VMD_TYPE_SEQ) is the exact equivalent.
</p>
<p>
V1.7
</p>
<p>
BOOST_VMD_AFTER_SEQ(sequence) looked for an seq at the beginning of a sequence
and returned the rest of the sequence or emptiness if no seq is found.
</p>
<p>
V1.8 equivalent
</p>
<p>
BOOST_VMD_ELEM(0,sequence,BOOST_VMD_TYPE_SEQ,BOOST_VMD_RETURN_ONLY_AFTER) is
the exact equivalent.
</p>
<p>
V1.7
</p>
<p>
BOOST_VMD_IS_BEGIN_SEQ(sequence,...) returns 1 if input begins with an seq,
else 0 if it does not.
</p>
<p>
V1.8 equivalent
</p>
<p>
BOOST_VMD_ELEM(0,sequence,BOOST_VMD_TYPE_SEQ) returns the seq found, otherwise
emptiness if not found. You can use BOOST_PP_COMPL(BOOST_VMD_IS_EMPTY(BOOST_VMD_ELEM(0,sequence,BOOST_VMD_TYPE_SEQ)))
as the exact equivalent.
</p>
<h4>
<a name="variadic_macro_data.vmd_conv.h5"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_conv.tuple"></a></span><a class="link" href="vmd_conv.html#variadic_macro_data.vmd_conv.tuple">Tuple</a>
</h4>
<p>
V1.7
</p>
<p>
BOOST_VMD_TUPLE(sequence) looked for an tuple at the beginning of a sequence
and returned a 2-element tuple, where the first element is the tuple and the
second tuple element is the rest of the sequence. If no tuple is found both
tuple elements are empty.
</p>
<p>
V1.8 equivalent
</p>
<p>
BOOST_VMD_ELEM(0,sequence,BOOST_VMD_TYPE_TUPLE,BOOST_VMD_RETURN_AFTER) is the
exact equivalent.
</p>
<p>
V1.7
</p>
<p>
BOOST_VMD_BEGIN_TUPLE(sequence) looked for a tuple at the beginning of a sequence
and returned the tuple if found or emptiness if no tuple is found.
</p>
<p>
V1.8 equivalent
</p>
<p>
BOOST_VMD_ELEM(0,sequence,BOOST_VMD_TYPE_TUPLE) is the exact equivalent.
</p>
<p>
V1.7
</p>
<p>
BOOST_VMD_AFTER_TUPLE(sequence) looked for an tuple at the beginning of a sequence
and returned the rest of the sequence or emptiness if no tuple is found.
</p>
<p>
V1.8 equivalent
</p>
<p>
BOOST_VMD_ELEM(0,sequence,BOOST_VMD_TYPE_TUPLE,BOOST_VMD_RETURN_ONLY_AFTER)
is the exact equivalent.
</p>
<p>
V1.7
</p>
<p>
BOOST_VMD_IS_BEGIN_TUPLE(sequence,...) returns 1 if input begins with an tuple,
else 0 if it does not.
</p>
<p>
V1.8 equivalent
</p>
<p>
BOOST_VMD_ELEM(0,sequence,BOOST_VMD_TYPE_TUPLE) returns the tuple found, otherwise
emptiness if not found. You can use BOOST_PP_COMPL(BOOST_VMD_IS_EMPTY(BOOST_VMD_ELEM(0,sequence,BOOST_VMD_TYPE_TUPLE)))
as the exact equivalent.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_vc_isms.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_examples.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,132 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Data types</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="prev" href="vmd_detail.html" title="Functional groups">
<link rel="next" href="vmd_specific.html" title="Specific macros for working with data types">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_detail.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_specific.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="variadic_macro_data.vmd_data_types"></a><a class="link" href="vmd_data_types.html" title="Data types">Data types</a>
</h2></div></div></div>
<p>
The VMD library has functionality for testing and parsing preprocessor data.
</p>
<p>
The C++ preprocessor defines preprocessor data as preprocessing tokens. The
types of preprocessing tokens can be seen in section 2.5 of the C++ standard
document.
</p>
<p>
The VMD library works with a subset of two of these types of preprocessor tokens
as "data types". These are the "identifier" and "pp-number"
preprocessor tokens. The preprocessor token types which VMD cannot parse are:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
header-name
</li>
<li class="listitem">
character-literal
</li>
<li class="listitem">
user-defined-characteral-literal
</li>
<li class="listitem">
string-literal
</li>
<li class="listitem">
user-defined-string-literal
</li>
<li class="listitem">
preprocessing-op-or-punc
</li>
</ul></div>
<p>
Even though VMD cannot parse these preprocessor token types, it is still a
very useful library since a large part of macro programming works with 'identifier'
and 'pp-number' tokens.
</p>
<p>
VMD identifiers are preprocessing tokens consisting of alphanumeric characters
and the underscore ( _ ) character. This is very similar to a preprocessor
token "identifier" with the difference being that a VMD identifier
can start with a numeric character, allowing VMD identifiers to also be positive
integral literals. VMD offers functionality for parsing VMD identifiers both
as a separate element or in a sequence of preprocessing tokens.
</p>
<p>
VMD numbers are Boost PP numbers, ie. preprocessing tokens of whole numbers
between 0 and 256 inclusive. These are a small subset of preprocessor token
"pp-number". VMD offers functionality for parsing numbers both as
a separate element or in a sequence of preprocessing tokens. A VMD number is
really a subset of VMD identifiers for which VMD offers specific functionality.
The Boost PP library has it own extensive support for numbers, which VMD does
not duplicate.
</p>
<p>
VMD v-types are, like numbers, a subset of VMD identifiers consisting of identifiers
beginning with BOOST_VMD_TYPE_ followed by a data type mnemonic. Each v-type
can be recognized by VMD functionality and therefore passed or returned by
macros. Like any identifier a v-type can be parsed both as a separate element
or in a sequence of preprocessing tokens.
</p>
<p>
VMD can also test for emptiness, or the absence of any preprocessing tokens
when passed as macro input.
</p>
<p>
The Boost PP library supports four individual high-level data types. These
are arrays, lists, seqs, and tuples. When using variadic macros arrays are
really obsolete since tuples have all the functionality of arrays with a simpler
syntax. Nonetheless arrays are fully supported by VMD. A further data type
supported by Boost PP is variadic data, which is a comma separated grouping
of preprocessor elements. VMD has no special support for variadic data outside
of what is already in Boost PP.
</p>
<p>
VMD has functionality to work with the four Boost PP high-level data types.
VMD can test the Boost PP data types and parse them in a sequence of preprocessor
tokens.
</p>
<p>
VMD can also parse sequences. A sequence consists of zero or more other top-level
data types already mentioned represented consecutively. As such a sequence
represents any data type which VMD can parse since it can consist of emptiness,
a single data type, or multiple data types represented consecutively.
</p>
<p>
Emptiness, the three identifier types, the four Boost PP composite data types,
and VMD sequences are the data types which VMD understands. Other low-level
preprocessor data types can of course be used in macro programming but VMD
cannot parse such preprocessor data.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_detail.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_specific.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,86 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Design</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="prev" href="../BOOST_VMD_IS_VMD_TUPLE.html" title="Macro BOOST_VMD_IS_VMD_TUPLE">
<link rel="next" href="vmd_compilers.html" title="Compilers">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../BOOST_VMD_IS_VMD_TUPLE.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_compilers.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="variadic_macro_data.vmd_design"></a><a class="link" href="vmd_design.html" title="Design">Design</a>
</h2></div></div></div>
<p>
The initial impetus for creating this library was entirely practical. I had
been working on another library of macro functionality, which used Boost PP
functionality, and I realized that if I could use variadic macros with my other
library, the end-user usability for that library would be easier. Therefore
the initial main design goal of this library was to interoperate variadic macro
data with Boost PP in the easiest and clearest way possible.
</p>
<p>
This led to the original versions of the library as an impetus for adding variadic
macro data support to Boost PP. While this was being done, but the variadic
macro data support had not yet been finalized in Boost PP, I still maintained
the library in two modes, either its own variadic data functionality or deferring
to the implementation of variadic macros in the Boost PP library.
</p>
<p>
Once support for variadic data had been added to Boost PP I stripped down the
functionality of this library to only include variadic macro support for functionality
which was an adjunct to the support in Boost PP. This functionality might be
seen as experimental, since it largely relied on a macro which tested for empty
input which Paul Mensonides, the author of Boost PP, had published on the Internet,
and which by the very nature of the C++ preprocessor is slightly flawed but
which was the closest approximation of such functionality which I believed
could be made. I had to tweak this macro somewhat for the Visual C++ preprocessor,
whose conformance to the C++ standard for macro processing is notably incorrect
in a number of areas. But I still felt this functionality could be used in
select situations and might be useful to others. Using this functionality I
was able to build up some other macros which tested for the various Boost PP
data types. I also was able to add in functionality, based on Paul Mendsonides
excellent work, for handling tuples in preprocessing data.
</p>
<p>
All of this particular functionality is impossible to do effectively without
the use of variadic macros. But I had kept these features at a minimum because
of the difficulty of using variadic macros with compilers, most notably Visual
C++, whose implementation of variadic macros is substandard and therefore very
difficult to get to work correctly when variadic macros must be used.
</p>
<p>
I then realized that if I am going to have a library which takes advantage
of variadic macros I should see what I could do in the area of parsing preprocessor
data. This has led to a reorganization of the library as a set of macros largely
for parsing preprocessor data. All of this is now built on top of my use of
the almost perfect checking for emptiness which Paul Mensonides originally
created.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../BOOST_VMD_IS_VMD_TUPLE.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_compilers.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,89 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Functional groups</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="prev" href="vmd_vc.html" title="Visual C++ define">
<link rel="next" href="vmd_data_types.html" title="Data types">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_vc.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_data_types.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="variadic_macro_data.vmd_detail"></a><a class="link" href="vmd_detail.html" title="Functional groups">Functional groups</a>
</h2></div></div></div>
<p>
The particular constructs for which VMD has functionality can be divided into
these categories:
</p>
<div class="orderedlist"><ol class="orderedlist" type="1">
<li class="listitem">
Emptiness
</li>
<li class="listitem">
Identifiers
</li>
<li class="listitem">
Numbers
</li>
<li class="listitem">
Types
</li>
<li class="listitem">
Boost PP data types ( array, list, seq, and tuple )
</li>
<li class="listitem">
Sequences
</li>
<li class="listitem">
Additional helper variadic macros
</li>
</ol></div>
<p>
The first six categories delineate the data types which VMD can parse. The
last category presents additional macros which will prove helpful for a macro
programmer using variadic macros with VMD and Boost PP.
</p>
<p>
A general explanation of each of these categories will follow in the appropriate
place in the documentation.
</p>
<p>
Furthermore VMD macros for working with the above data types which VMD understands
can be divided into 'specific' and 'generic' macros.
</p>
<p>
The specific macros ask whether some input data is a particular data type.
The generic macros work with input data as any data type while allowing the
programmer to separately query the type of data.
</p>
<p>
Both specific and generic macros have their place and the macro programmer
can decide which to use for any given situation.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_vc.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_data_types.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,71 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Input as dynamic types</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="prev" href="vmd_reentrant.html" title="Boost PP re-entrant versions">
<link rel="next" href="vmd_vc_isms.html" title="Visual C++ gotchas in VMD">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_reentrant.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_vc_isms.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="variadic_macro_data.vmd_dynamic_typing"></a><a class="link" href="vmd_dynamic_typing.html" title="Input as dynamic types">Input as dynamic
types</a>
</h2></div></div></div>
<p>
Within the constraints based on the top-level types which VMD can parse, the
libraries gives the end-user the ability to design macros with dynamic data
types. By this I mean that a macro could be designed to handle different data
types based on some documented agreement of different combinations of macro
input meaning slightly different things. Add to this the ability to design
such macros with variadic parameters and we have a preprocessor system of macro
creation which to a lesser extent rivals the DSELS of template metaprogramming.
Of course the preprocessor is not nearly as flexible as C++ templates, but
still the sort of preprocessor metaprogramming one could do with VMD, and the
underlying Boost PP, in creating flexible macros which can handle different
combinations of data types is very interesting.
</p>
<p>
Of course macros need to be usable by an end-user so the syntactical ability
of sequences to represent different types of input data must be balanced against
ease of use and understanding when using a macro. But because certain sequences
can mimic C++ function calls to some extent it is possible to represent macros
as a language closer to C++ with VMD.
</p>
<p>
What is important when designing a macro in which you parse input to decide
which type of data the invoker is passing to your macro is that you are aware
of the constraints when parsing a data type. As an example if you design a
macro where some input can either be a number, an identifier, or some other
data type top-level input then attempting to parse the data to see if it is
a number or identifier could fail with a preprocessor error and nullify your
design if the data is not a VMD data type. So designing a macro with data types
in mind often means restricting data to parseable top-level types.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_reentrant.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_vc_isms.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,994 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Examples using VMD functionality</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="prev" href="vmd_conv.html" title="Version 1.7 to 1.8 conversion">
<link rel="next" href="../variadic_macro_data_reference.html" title="Variadic Macro Data Reference">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_conv.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../variadic_macro_data_reference.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="variadic_macro_data.vmd_examples"></a><a class="link" href="vmd_examples.html" title="Examples using VMD functionality">Examples using VMD functionality</a>
</h2></div></div></div>
<p>
Examples of library use are always highly personal. Any given library employing
macro programming can decide what macro facilities are needed based on the
library itself and then decide if functionality in a macro library like VMD
makes macro programming in that library easier. To that end the examples presented
here are highly arbitrary and are just efforts to illustrate possible use of
functionality of VMD features without worrying too much if those examples have
any practical beneficial use in real programming situations. In these examples
I have endeavored, therefore, to present macro programming "snippets"
using VMD functionality rather than complete solutions to a given practical
problem.
</p>
<h4>
<a name="variadic_macro_data.vmd_examples.h0"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_examples.switch_macro"></a></span><a class="link" href="vmd_examples.html#variadic_macro_data.vmd_examples.switch_macro">Switch
macro</a>
</h4>
<p>
In C++ there is a 'switch' statement which we can emulate in macro programming
using VMD. For the macro emulation we will have as parameters to our macro:
</p>
<div class="orderedlist"><ol class="orderedlist" type="1">
<li class="listitem">
A value, which can be any data type VMD can parse.
</li>
<li class="listitem">
A tuple of calling values. These will be used when calling the matching
macro.
</li>
<li class="listitem">
Variadic parameters, each of which are tuples. Each tuple consists of two
elements, the name of a value to match and the name of a macro to call.
For the 'default' case the tuple is a single element which is the name
of a macro to call. These are our equivalents to the C++ switch 'case'
statements.
</li>
</ol></div>
<p>
The macro looks like:
</p>
<pre class="programlisting"><span class="identifier">BOOST_VMD_SWITCH</span><span class="special">(</span><span class="identifier">value</span><span class="special">,</span><span class="identifier">calling_values</span><span class="special">,...)</span>
</pre>
<p>
We have to be careful not to parse the name of our macro to call in any way
since this is a failing condition for BOOST_VMD_IS_EMPTY and subsequently for
any parsing of input data we might want to do. Instead we will just extract
the calling macro name and just call it, passing the calling values.
</p>
<p>
Our processing is:
</p>
<div class="orderedlist"><ol class="orderedlist" type="1">
<li class="listitem">
Convert our variadic parameters to a tuple since access to tuple elements
is easier.
</li>
<li class="listitem">
Use a BOOST_PP_WHILE loop to find the matching value and extract the calling
macro from it. We will use BOOST_VMD_EQUAL to find the matching value.
</li>
<li class="listitem">
Call the calling macro with the calling values when we return from our
BOOST_PP_WHILE loop.
</li>
</ol></div>
<p>
Here is our code:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">detail</span><span class="special">/</span><span class="identifier">setup</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#if</span> <span class="identifier">BOOST_PP_VARIADICS</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">cat</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">arithmetic</span><span class="special">/</span><span class="identifier">inc</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">comparison</span><span class="special">/</span><span class="identifier">equal</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">control</span><span class="special">/</span><span class="identifier">expr_iif</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">control</span><span class="special">/</span><span class="identifier">iif</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">control</span><span class="special">/</span><span class="keyword">while</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">tuple</span><span class="special">/</span><span class="identifier">elem</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">tuple</span><span class="special">/</span><span class="keyword">enum</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">facilities</span><span class="special">/</span><span class="identifier">expand</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">tuple</span><span class="special">/</span><span class="identifier">replace</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">tuple</span><span class="special">/</span><span class="identifier">size</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">variadic</span><span class="special">/</span><span class="identifier">to_tuple</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">variadic</span><span class="special">/</span><span class="identifier">size</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">equal</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">identity</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_empty</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="comment">/*
State index into state values
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_STATE_ELEM_INDEX</span> <span class="number">2</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_STATE_ELEM_DEFAULT</span> <span class="number">4</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_STATE_ELEM_RESULT</span> <span class="number">5</span>
<span class="comment">/*
Retrieve the state value, never changes
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_STATE_GET_VALUE</span><span class="special">(</span><span class="identifier">state</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_TUPLE_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">state</span><span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="comment">/*
Retrieve the state tuple of values, never changes
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_STATE_GET_CHOICES</span><span class="special">(</span><span class="identifier">state</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_TUPLE_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">state</span><span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="comment">/*
Retrieve the state index
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_STATE_GET_INDEX</span><span class="special">(</span><span class="identifier">state</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_TUPLE_ELEM</span><span class="special">(</span><span class="number">2</span><span class="special">,</span><span class="identifier">state</span><span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="comment">/*
Retrieve the state tuple of values size, never changes
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_STATE_GET_SIZE</span><span class="special">(</span><span class="identifier">state</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_TUPLE_ELEM</span><span class="special">(</span><span class="number">3</span><span class="special">,</span><span class="identifier">state</span><span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="comment">/*
Retrieve the state default tuple
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_STATE_GET_DEFAULT</span><span class="special">(</span><span class="identifier">state</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_TUPLE_ELEM</span><span class="special">(</span><span class="number">4</span><span class="special">,</span><span class="identifier">state</span><span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="comment">/*
Retrieve the state result tuple
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_STATE_GET_RESULT</span><span class="special">(</span><span class="identifier">state</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_TUPLE_ELEM</span><span class="special">(</span><span class="number">5</span><span class="special">,</span><span class="identifier">state</span><span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="comment">/*
Retrieve the current value tuple
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_STATE_GET_CURRENT_CHOICE</span><span class="special">(</span><span class="identifier">state</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_TUPLE_ELEM</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_STATE_GET_INDEX</span><span class="special">(</span><span class="identifier">state</span><span class="special">),</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_STATE_GET_CHOICES</span><span class="special">(</span><span class="identifier">state</span><span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="comment">/*
Expands to the state
value = value to compare against
tuple = choices as a tuple of values
size = size of tuple of values
None of these ever change in the WHILE state
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_STATE_EXPAND</span><span class="special">(</span><span class="identifier">value</span><span class="special">,</span><span class="identifier">tuple</span><span class="special">,</span><span class="identifier">size</span><span class="special">)</span> <span class="special">\</span>
<span class="special">(</span><span class="identifier">value</span><span class="special">,</span><span class="identifier">tuple</span><span class="special">,</span><span class="number">0</span><span class="special">,</span><span class="identifier">size</span><span class="special">,(</span><span class="number">0</span><span class="special">,),(,))</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="comment">/*
Expands to the WHILE state
The state to our WHILE consists of a tuple of elements:
1: value to compare against
2: tuple of values. Each value is a value/macro pair or if the default just a macro
3: index into the values
4: tuple for default macro. 0 means no default macro, 1 means default macro and then second value is the default macro.
5: tuple of result matched. Emptiness means no result yet specified, 0 means no match, 1 means match and second value is the matching macro.
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_STATE</span><span class="special">(</span><span class="identifier">value</span><span class="special">,...)</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_STATE_EXPAND</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">value</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_VARIADIC_TO_TUPLE</span><span class="special">(</span><span class="identifier">__VA_ARGS__</span><span class="special">),</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_VARIADIC_SIZE</span><span class="special">(</span><span class="identifier">__VA_ARGS__</span><span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="comment">/*
Sets the state upon a successful match.
macro = is the matching macro found
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_OP_SUCCESS</span><span class="special">(</span><span class="identifier">d</span><span class="special">,</span><span class="identifier">state</span><span class="special">,</span><span class="identifier">macro</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_TUPLE_REPLACE_D</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">d</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">state</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_STATE_ELEM_RESULT</span><span class="special">,</span> <span class="special">\</span>
<span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">macro</span><span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="comment">/*
Sets the state upon final failure to find a match.
def = default tuple macro, ignored
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_OP_FAILURE</span><span class="special">(</span><span class="identifier">d</span><span class="special">,</span><span class="identifier">state</span><span class="special">,</span><span class="identifier">def</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_TUPLE_REPLACE_D</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">d</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">state</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_STATE_ELEM_RESULT</span><span class="special">,</span> <span class="special">\</span>
<span class="special">(</span><span class="number">0</span><span class="special">,)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="comment">/*
Increments the state index into the tuple values
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_OP_UPDATE_INDEX</span><span class="special">(</span><span class="identifier">d</span><span class="special">,</span><span class="identifier">state</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_TUPLE_REPLACE_D</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">d</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">state</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_STATE_ELEM_INDEX</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_INC</span><span class="special">(</span><span class="identifier">BOOST_VMD_SWITCH_STATE_GET_INDEX</span><span class="special">(</span><span class="identifier">state</span><span class="special">))</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="comment">/*
Choose our current value's macro as our successful match
tuple = current tuple to test
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_OP_TEST_CURRENT_VALUE_MATCH</span><span class="special">(</span><span class="identifier">d</span><span class="special">,</span><span class="identifier">state</span><span class="special">,</span><span class="identifier">tuple</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_OP_SUCCESS</span><span class="special">(</span><span class="identifier">d</span><span class="special">,</span><span class="identifier">state</span><span class="special">,</span><span class="identifier">BOOST_PP_TUPLE_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">tuple</span><span class="special">))</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="comment">/*
Update our state index
tuple = current tuple to test, ignored
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_OP_TEST_CURRENT_VALUE_UPDATE_INDEX</span><span class="special">(</span><span class="identifier">d</span><span class="special">,</span><span class="identifier">state</span><span class="special">,</span><span class="identifier">tuple</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_OP_UPDATE_INDEX</span><span class="special">(</span><span class="identifier">d</span><span class="special">,</span><span class="identifier">state</span><span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="comment">/*
Test our current value against our value to compare against
tuple = current tuple to test
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_OP_TEST_CURRENT_VALUE</span><span class="special">(</span><span class="identifier">d</span><span class="special">,</span><span class="identifier">state</span><span class="special">,</span><span class="identifier">tuple</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_IIF</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_EQUAL_D</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">d</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_STATE_GET_VALUE</span><span class="special">(</span><span class="identifier">state</span><span class="special">),</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_TUPLE_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">tuple</span><span class="special">)</span> <span class="special">\</span>
<span class="special">),</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_OP_TEST_CURRENT_VALUE_MATCH</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_OP_TEST_CURRENT_VALUE_UPDATE_INDEX</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">(</span><span class="identifier">d</span><span class="special">,</span><span class="identifier">state</span><span class="special">,</span><span class="identifier">tuple</span><span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="comment">/*
Set our default macro and update the index in our WHILE state
tuple = current tuple to test
*/</span>
<span class="preprocessor">#if</span> <span class="identifier">BOOST_VMD_MSVC</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_OP_TEST_CURRENT_CREATE_DEFAULT_NN</span><span class="special">(</span><span class="identifier">number</span><span class="special">,</span><span class="identifier">name</span><span class="special">)</span> <span class="special">\</span>
<span class="special">(</span><span class="identifier">number</span><span class="special">,</span><span class="identifier">name</span><span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_OP_TEST_CURRENT_CREATE_DEFAULT</span><span class="special">(</span><span class="identifier">d</span><span class="special">,</span><span class="identifier">state</span><span class="special">,</span><span class="identifier">tuple</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_OP_UPDATE_INDEX</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">d</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_TUPLE_REPLACE_D</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">d</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">state</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_STATE_ELEM_DEFAULT</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_OP_TEST_CURRENT_CREATE_DEFAULT_NN</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">BOOST_PP_TUPLE_ENUM</span><span class="special">(</span><span class="identifier">tuple</span><span class="special">))</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="preprocessor">#else</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_OP_TEST_CURRENT_CREATE_DEFAULT</span><span class="special">(</span><span class="identifier">d</span><span class="special">,</span><span class="identifier">state</span><span class="special">,</span><span class="identifier">tuple</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_OP_UPDATE_INDEX</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">d</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_TUPLE_REPLACE_D</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">d</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">state</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_STATE_ELEM_DEFAULT</span><span class="special">,</span> <span class="special">\</span>
<span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">BOOST_PP_TUPLE_ENUM</span><span class="special">(</span><span class="identifier">tuple</span><span class="special">))</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="preprocessor">#endif</span>
<span class="comment">/*
If our current value is a default macro, just set the default macro,
else test our current value.
tuple = current tuple to test
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_OP_TEST_CURRENT_TUPLE</span><span class="special">(</span><span class="identifier">d</span><span class="special">,</span><span class="identifier">state</span><span class="special">,</span><span class="identifier">tuple</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_IIF</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_EQUAL_D</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">d</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_TUPLE_SIZE</span><span class="special">(</span><span class="identifier">tuple</span><span class="special">),</span> <span class="special">\</span>
<span class="number">1</span> <span class="special">\</span>
<span class="special">),</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_OP_TEST_CURRENT_CREATE_DEFAULT</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_OP_TEST_CURRENT_VALUE</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">(</span><span class="identifier">d</span><span class="special">,</span><span class="identifier">state</span><span class="special">,</span><span class="identifier">tuple</span><span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="comment">/*
Test the current value in our tuple of values
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_OP_TEST_CURRENT</span><span class="special">(</span><span class="identifier">d</span><span class="special">,</span><span class="identifier">state</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_OP_TEST_CURRENT_TUPLE</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">d</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">state</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_STATE_GET_CURRENT_CHOICE</span><span class="special">(</span><span class="identifier">state</span><span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="comment">/*
Choose the default macro as our successful match
def = default tuple consisting of just the default macro name
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_OP_DEFAULT_RET_CHOSEN</span><span class="special">(</span><span class="identifier">d</span><span class="special">,</span><span class="identifier">state</span><span class="special">,</span><span class="identifier">def</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_OP_SUCCESS</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">d</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">state</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_TUPLE_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">def</span><span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="comment">/*
If the default macro exists, choose it else indicate no macro was found
def = default tuple consisting of just the default macro name
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_OP_DEFAULT_RET</span><span class="special">(</span><span class="identifier">d</span><span class="special">,</span><span class="identifier">state</span><span class="special">,</span><span class="identifier">def</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_IIF</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_TUPLE_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">def</span><span class="special">),</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_OP_DEFAULT_RET_CHOSEN</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_OP_FAILURE</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">(</span><span class="identifier">d</span><span class="special">,</span><span class="identifier">state</span><span class="special">,</span><span class="identifier">def</span><span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="comment">/*
Try to choose the default macro if it exists
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_OP_DEFAULT</span><span class="special">(</span><span class="identifier">d</span><span class="special">,</span><span class="identifier">state</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_OP_DEFAULT_RET</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">d</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">state</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_STATE_GET_DEFAULT</span><span class="special">(</span><span class="identifier">state</span><span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="comment">/*
WHILE loop operation
Check for the next value match or try to choose the default if all matches have been checked
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_OP</span><span class="special">(</span><span class="identifier">d</span><span class="special">,</span><span class="identifier">state</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_IIF</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_EQUAL_D</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">d</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_STATE_GET_INDEX</span><span class="special">(</span><span class="identifier">state</span><span class="special">),</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_STATE_GET_SIZE</span><span class="special">(</span><span class="identifier">state</span><span class="special">)</span> <span class="special">\</span>
<span class="special">),</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_OP_DEFAULT</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_OP_TEST_CURRENT</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">(</span><span class="identifier">d</span><span class="special">,</span><span class="identifier">state</span><span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="comment">/*
WHILE loop predicate
Continue the WHILE loop if a result has not yet been specified
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_PRED</span><span class="special">(</span><span class="identifier">d</span><span class="special">,</span><span class="identifier">state</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_IS_EMPTY</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_TUPLE_ELEM</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="number">0</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_STATE_GET_RESULT</span><span class="special">(</span><span class="identifier">state</span><span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="comment">/*
Invokes the function-like macro
macro = function-like macro name
tparams = tuple of macro parameters
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_PROCESS_INVOKE_MACRO</span><span class="special">(</span><span class="identifier">macro</span><span class="special">,</span><span class="identifier">tparams</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_EXPAND</span><span class="special">(</span><span class="identifier">macro</span> <span class="identifier">tparams</span><span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="comment">/*
Processes our WHILE loop result
callp = tuple of parameters for the called macro
result = tuple. The first tuple element is 0
if no macro has been found or 1 if a macro
has been found. If 1 the second element is
the name of a function-like macro
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_PROCESS</span><span class="special">(</span><span class="identifier">callp</span><span class="special">,</span><span class="identifier">result</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_EXPR_IIF</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_TUPLE_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">result</span><span class="special">),</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_PROCESS_INVOKE_MACRO</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_TUPLE_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">result</span><span class="special">),</span> <span class="special">\</span>
<span class="identifier">callp</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="comment">/*
Use BOOST_VMD_SWITCH_IDENTITY to pass a fixed value instead
of a function-like macro as the second element of
any tuple of the variadic parameters, or as the default
value, to BOOST_VMD_SWITCH.
*/</span>
<span class="preprocessor">#if</span> <span class="identifier">BOOST_VMD_MSVC</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_IDENTITY</span><span class="special">(</span><span class="identifier">item</span><span class="special">)</span> <span class="identifier">BOOST_PP_CAT</span><span class="special">(</span><span class="identifier">BOOST_VMD_IDENTITY</span><span class="special">(</span><span class="identifier">item</span><span class="special">),)</span>
<span class="preprocessor">#else</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_IDENTITY</span> <span class="identifier">BOOST_VMD_IDENTITY</span>
<span class="preprocessor">#endif</span>
<span class="comment">/*
Switch macro
Parameters are:
value = value to compare against. May be any VMD data value.
callp = tuple of parameters for the called macro
variadic parameters = each parameter must be a tuple.
Each tuple consists of a two-element tuple. The first element is
a value, which may be any VMD data value, and the second element
is the name of a function-like macro to be called if the value
is equal to the value to compare against. For a default value
the tuple is a single-element tuple which contains the name of
a function-like macro to be called if no other value matches.
*/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH</span><span class="special">(</span><span class="identifier">value</span><span class="special">,</span><span class="identifier">callp</span><span class="special">,...)</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_PROCESS</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">callp</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_STATE_GET_RESULT</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_WHILE</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_PRED</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_OP</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH_STATE</span><span class="special">(</span><span class="identifier">value</span><span class="special">,</span><span class="identifier">__VA_ARGS__</span><span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="preprocessor">#endif</span> <span class="comment">/* BOOST_PP_VARIADICS */</span>
</pre>
<p>
The code is fairly involved but it is commented so that it can be understood.
There are a few workarounds for a VC++ preprocessor problem, which I discovered,
having to do with passing the name of a function-like macro in a tuple.
</p>
<p>
The BOOST_VMD_SWITCH macro can be used with either macros to call or with fixed
values to return. When specifying macros to call the macro name is the second
element of the corresponding value-macro tuple, or in the 'default' case it
is just the macro name itself. When specifying fixed values to return the macro
'name' is BOOST_VMD_SWITCH_IDENTITY(fixed_value), whether as the second element
of the corresponding value-macro tuple or as the macro 'name' of the 'default'
case. In the variadic parameters the user can mix macro names and fixed values
as he likes.
</p>
<p>
Some simple examples:
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_TEST_1</span><span class="special">(</span><span class="identifier">number</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">test1_</span> <span class="special">##</span> <span class="identifier">number</span>
<span class="comment">/**/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_TEST_2</span><span class="special">(</span><span class="identifier">number</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">test2_</span> <span class="special">##</span> <span class="identifier">number</span>
<span class="comment">/**/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_TEST_3</span><span class="special">(</span><span class="identifier">number</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">test3_</span> <span class="special">##</span> <span class="identifier">number</span>
<span class="comment">/**/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SWITCH_TEST_DEFAULT</span><span class="special">(</span><span class="identifier">number</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">test_default_</span> <span class="special">##</span> <span class="identifier">number</span>
<span class="comment">/**/</span>
</pre>
<p>
We will use these simple macros in our calls to BOOST_VMD_SWITCH.
</p>
<pre class="programlisting"><span class="identifier">BOOST_VMD_SWITCH</span><span class="special">(</span><span class="number">1</span><span class="special">,</span>
<span class="special">(</span><span class="number">7</span><span class="special">),</span>
<span class="special">(</span><span class="identifier">BOOST_VMD_SWITCH_TEST_DEFAULT</span><span class="special">),</span>
<span class="special">(</span><span class="number">3</span><span class="special">,</span><span class="identifier">BOOST_VMD_SWITCH_TEST_3</span><span class="special">),</span>
<span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">BOOST_VMD_SWITCH_TEST_1</span><span class="special">),</span>
<span class="special">(</span><span class="number">2</span><span class="special">,</span><span class="identifier">BOOST_VMD_SWITCH_TEST_2</span><span class="special">)</span>
<span class="special">)</span>
</pre>
<p>
Here our macro will return 'test1_7'.
</p>
<p>
Notice that 'cases' can be in any order.
</p>
<pre class="programlisting"><span class="identifier">BOOST_VMD_SWITCH</span><span class="special">(</span><span class="number">4</span><span class="special">,</span>
<span class="special">(</span><span class="number">7</span><span class="special">),</span>
<span class="special">(</span><span class="identifier">BOOST_VMD_SWITCH_TEST_DEFAULT</span><span class="special">),</span>
<span class="special">(</span><span class="number">2</span><span class="special">,</span><span class="identifier">BOOST_VMD_SWITCH_TEST_2</span><span class="special">),</span>
<span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">BOOST_VMD_SWITCH_TEST_1</span><span class="special">),</span>
<span class="special">(</span><span class="number">3</span><span class="special">,</span><span class="identifier">BOOST_VMD_SWITCH_TEST_3</span><span class="special">)</span>
<span class="special">)</span>
</pre>
<p>
Here are macro uses the default case and returns 'test_default_7'.
</p>
<pre class="programlisting"><span class="identifier">BOOST_VMD_SWITCH</span><span class="special">(</span><span class="number">143</span><span class="special">,</span>
<span class="special">(</span><span class="number">7</span><span class="special">),</span>
<span class="special">(</span><span class="identifier">BOOST_VMD_SWITCH_TEST_DEFAULT</span><span class="special">),</span>
<span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">BOOST_VMD_SWITCH_TEST_1</span><span class="special">),</span>
<span class="special">(</span><span class="number">2</span><span class="special">,</span><span class="identifier">BOOST_VMD_SWITCH_TEST_2</span><span class="special">),</span>
<span class="special">(</span><span class="number">3</span><span class="special">,</span><span class="identifier">BOOST_VMD_SWITCH_TEST_3</span><span class="special">),</span>
<span class="special">(</span><span class="number">143</span><span class="special">,</span><span class="identifier">BOOST_VMD_SWITCH_IDENTITY</span><span class="special">(</span><span class="number">55</span><span class="special">))</span>
<span class="special">)</span>
</pre>
<p>
This shows how the matching case can be a fixed_value as the macro 'name'.
</p>
<pre class="programlisting"><span class="identifier">BOOST_VMD_SWITCH</span><span class="special">(</span><span class="number">155</span><span class="special">,</span>
<span class="special">(</span><span class="number">7</span><span class="special">),</span>
<span class="special">(</span><span class="identifier">BOOST_VMD_SWITCH_IDENTITY</span><span class="special">(</span><span class="number">77</span><span class="special">)),</span>
<span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">BOOST_VMD_SWITCH_TEST_1</span><span class="special">),</span>
<span class="special">(</span><span class="number">2</span><span class="special">,</span><span class="identifier">BOOST_VMD_SWITCH_TEST_2</span><span class="special">),</span>
<span class="special">(</span><span class="number">3</span><span class="special">,</span><span class="identifier">BOOST_VMD_SWITCH_TEST_3</span><span class="special">),</span>
<span class="special">(</span><span class="number">143</span><span class="special">,</span><span class="identifier">BOOST_VMD_SWITCH_IDENTITY</span><span class="special">(</span><span class="number">55</span><span class="special">))</span>
<span class="special">)</span>
</pre>
<p>
This shows how the default value can be a fixed_value as the macro 'name'.
</p>
<pre class="programlisting"><span class="identifier">BOOST_VMD_SWITCH</span><span class="special">(</span><span class="identifier">BOOST_VMD_TYPE_TUPLE</span><span class="special">,</span>
<span class="special">(</span><span class="number">7</span><span class="special">),</span>
<span class="special">(</span><span class="identifier">BOOST_VMD_SWITCH_TEST_DEFAULT</span><span class="special">),</span>
<span class="special">(</span><span class="identifier">BOOST_VMD_TYPE_TUPLE</span><span class="special">,</span><span class="identifier">BOOST_VMD_SWITCH_TEST_1</span><span class="special">),</span>
<span class="special">((</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">,</span><span class="number">3</span><span class="special">),</span><span class="identifier">BOOST_VMD_SWITCH_TEST_3</span><span class="special">),</span>
<span class="special">(</span><span class="number">2</span><span class="special">,</span><span class="identifier">BOOST_VMD_SWITCH_TEST_2</span><span class="special">)</span>
<span class="special">)</span>
</pre>
<p>
This shows that the 'value' and each 'case' matching values can be different
data types just as long as the types are one which VMD can parse.
</p>
<p>
There is more that can be done with the BOOST_VMD_SWITCH code but as it is
I believe it could be useful for programmers writing macro code. For instance
there is no checking that more than one 'case' value is the same. We could
generate a BOOST_VMD_ASSERT if that were the situation. There is no concept
of falling through to the next 'case' as their is when 'break' is not used
at the bottom of a particular C++ 'case' statement. Nonetheless the example
gives the macro programmer an idea of what can be done using the BOOST_VMD_EQUAL
macro in treating data types generically, using BOOST_VMD_IS_EMPTY to test
for emptiness and using BOOST_VMD_IDENTITY to generate a fixed value when a
macro call is made.
</p>
<h4>
<a name="variadic_macro_data.vmd_examples.h1"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_examples.tti_inner_template"></a></span><a class="link" href="vmd_examples.html#variadic_macro_data.vmd_examples.tti_inner_template">TTI
inner template</a>
</h4>
<p>
As a more practical example, just to show the possible use of VMD functionality
in current Boost code, I will briefly illustrate a change that could be made
to the TTI library when using VMD functionality.
</p>
<p>
The Boost TTI library, of which the current developer of VMD is also the developer,
specifies a way to introspect an inner class template of a class. The introspection
can occur for an inner class template of specific template parameters.
</p>
<p>
In the library a macro is used to generate the metafunction which allows the
introspection to work. The macro used is called BOOST_TTI_TEMPLATE. The macro
has both a variadic version and a non-variadic version.
</p>
<p>
In the non-variadic version the macro always takes two parameters for introspecting
for specific template parameters. The first parameter is the name of the template
and the second parameter is an array of the specific template parameters (
with or without the parameter names themselves ). So for a class template of
the form:
</p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">X</span><span class="special">,</span><span class="keyword">int</span> <span class="identifier">Y</span><span class="special">&gt;</span> <span class="keyword">class</span> <span class="identifier">MyTemplate</span> <span class="special">{</span> <span class="special">...</span> <span class="identifier">code</span> <span class="special">};</span>
</pre>
<p>
the non-variadic macro would be:
</p>
<pre class="programlisting"><span class="identifier">BOOST_TTI_TEMPLATE</span><span class="special">(</span><span class="identifier">MyTemplate</span><span class="special">,(</span><span class="number">2</span><span class="special">,(</span><span class="keyword">class</span><span class="special">,</span><span class="keyword">int</span><span class="special">)))</span> <span class="comment">// uses array</span>
</pre>
<p>
I chose a Boost PP array rather than a Boost PP seq or a Boost PP list as I
felt the notation for specifying the template parameters was closer with the
array than with the others. Choosing a Boost PP tuple was not an option since
for non-variadic macros there is no way to automatically know the tuple size,
so an array was preferred.
</p>
<p>
For the variadic version variadic parameters are used so the notation would
be:
</p>
<pre class="programlisting"><span class="identifier">BOOST_TTI_TEMPLATE</span><span class="special">(</span><span class="identifier">MyTemplate</span><span class="special">,</span><span class="keyword">class</span><span class="special">,</span><span class="keyword">int</span><span class="special">)</span> <span class="comment">// uses variadic parameters</span>
</pre>
<p>
since this is the most natural notation.
</p>
<p>
But for compatibility with the non-variadic version the end-user with variadic
macro support could also choose the Boost PP array form above.
</p>
<p>
Using VMD the variadic version could support any of the other Boost PP composite
types for the specific template parameters, even though I feel that the variadic
parameters form is easiest to use. In this scenario a user could specify:
</p>
<pre class="programlisting"><span class="identifier">BOOST_TTI_TEMPLATE</span><span class="special">(</span><span class="identifier">MyTemplate</span><span class="special">,(</span><span class="keyword">class</span><span class="special">,(</span><span class="keyword">int</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">)))</span> <span class="comment">// use a list</span>
</pre>
<p>
or
</p>
<pre class="programlisting"><span class="identifier">BOOST_TTI_TEMPLATE</span><span class="special">(</span><span class="identifier">MyTemplate</span><span class="special">,(</span><span class="keyword">class</span><span class="special">)(</span><span class="keyword">int</span><span class="special">))</span> <span class="comment">// use a seq</span>
</pre>
<p>
or
</p>
<pre class="programlisting"><span class="identifier">BOOST_TTI_TEMPLATE</span><span class="special">(</span><span class="identifier">MyTemplate</span><span class="special">,(</span><span class="keyword">class</span><span class="special">,</span><span class="keyword">int</span><span class="special">))</span> <span class="comment">// use a tuple</span>
</pre>
<p>
The only change needed would be in the code which takes the second parameter
and converts it to the final form used internally ( a Boost PP array ). This
occurs in the macro BOOST_TTI_DETAIL_TRAIT_CALL_HAS_TEMPLATE_CHECK_PARAMS in
the &lt;boost/tti/detail/dtemplate_params.hpp&gt; file. The code has two situations,
one for VC++8 or below and one for all other compilers. For our example we
will concentrate just on the one for all other compilers. You do not need to
know what the code does internally to complete the creation of the appropriate
metafunction to follow this example. The macro code in question looks like
this:
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">BOOST_TTI_DETAIL_TRAIT_CALL_HAS_TEMPLATE_CHECK_PARAMS</span><span class="special">(</span><span class="identifier">trait</span><span class="special">,</span><span class="identifier">name</span><span class="special">,</span><span class="identifier">tpArray</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_TTI_DETAIL_HAS_MEMBER_WITH_TEMPLATE_SFINAE</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="special">(</span> <span class="identifier">BOOST_PP_ADD</span><span class="special">(</span><span class="identifier">BOOST_PP_ARRAY_SIZE</span><span class="special">(</span><span class="identifier">tpArray</span><span class="special">),</span><span class="number">4</span><span class="special">),</span> <span class="special">(</span> <span class="identifier">trait</span><span class="special">,</span> <span class="identifier">name</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="keyword">false</span><span class="special">,</span> <span class="identifier">BOOST_PP_ARRAY_ENUM</span><span class="special">(</span><span class="identifier">tpArray</span><span class="special">)</span> <span class="special">)</span> <span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
</pre>
<p>
In this code we are taking the name of the metafunction ( trait ), the name
of the template ( name ), and our specific template parameters ( tpArray )
and passing the information in the form of a Boost PP array to another macro,
which will eventually create the metafunction which the end-user uses to test
if such a class template exists within some enclosing class. Even if tpArray
were a list, seq, or tuple we still want to pass the information internally
to BOOST_TTI_DETAIL_HAS_MEMBER_WITH_TEMPLATE_SFINAE in the form you can see
above, which is a Boost PP array. We don't need or want to change that internal
representation.
</p>
<p>
The current code, used by both the non-variadic and variadic version of the
BOOST_TTI_TEMPLATE template, assumes the 'tpArray' parameter is a Boost PP
array. But if it could be a tuple, seq, or list in the variadic version the
code could become, with the appropriate Boost PP and VMD header files:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">arithmetic</span><span class="special">/</span><span class="identifier">add</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">array</span><span class="special">/</span><span class="keyword">enum</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">array</span><span class="special">/</span><span class="identifier">size</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">control</span><span class="special">/</span><span class="identifier">expr_iif</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">control</span><span class="special">/</span><span class="identifier">iif</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">list</span><span class="special">/</span><span class="keyword">enum</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">list</span><span class="special">/</span><span class="identifier">size</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">seq</span><span class="special">/</span><span class="keyword">enum</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">seq</span><span class="special">/</span><span class="identifier">size</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">tuple</span><span class="special">/</span><span class="keyword">enum</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">tuple</span><span class="special">/</span><span class="identifier">size</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">identity</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_array</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_list</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_seq</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_tuple</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#if</span> <span class="identifier">BOOST_PP_VARIADICS</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_TTI_DETAIL_TRAIT_CALL_HAS_TEMPLATE_CHECK_PARAMS</span><span class="special">(</span><span class="identifier">trait</span><span class="special">,</span><span class="identifier">name</span><span class="special">,</span><span class="identifier">tpArray</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_TTI_DETAIL_HAS_MEMBER_WITH_TEMPLATE_SFINAE</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_TTI_DETAIL_TRAIT_CALL_HAS_TEMPLATE_CHECK_PARAMS_TYPE_CONCAT</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">trait</span><span class="special">,</span><span class="identifier">name</span><span class="special">,</span><span class="identifier">tpArray</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_TTI_DETAIL_TRAIT_CALL_HAS_TEMPLATE_CHECK_PARAMS_TYPE</span><span class="special">(</span><span class="identifier">tpArray</span><span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_TTI_DETAIL_TRAIT_CALL_HAS_TEMPLATE_CHECK_PARAMS_TYPE</span><span class="special">(</span><span class="identifier">tpArray</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_IDENTITY_RESULT</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_IIF</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_IS_ARRAY</span><span class="special">(</span><span class="identifier">tpArray</span><span class="special">),</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_IDENTITY</span><span class="special">(</span><span class="identifier">ARRAY</span><span class="special">),</span> <span class="special">\</span>
<span class="identifier">BOOST_TTI_DETAIL_TRAIT_CALL_HAS_TEMPLATE_CHECK_PARAMS_TYPE_LIST</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">(</span><span class="identifier">tpArray</span><span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_TTI_DETAIL_TRAIT_CALL_HAS_TEMPLATE_CHECK_PARAMS_TYPE_LIST</span><span class="special">(</span><span class="identifier">tpArray</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_IDENTITY_RESULT</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_IIF</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_IS_LIST</span><span class="special">(</span><span class="identifier">tpArray</span><span class="special">),</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_IDENTITY</span><span class="special">(</span><span class="identifier">LIST</span><span class="special">),</span> <span class="special">\</span>
<span class="identifier">BOOST_TTI_DETAIL_TRAIT_CALL_HAS_TEMPLATE_CHECK_PARAMS_TYPE_SEQ</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">(</span><span class="identifier">tpArray</span><span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_TTI_DETAIL_TRAIT_CALL_HAS_TEMPLATE_CHECK_PARAMS_TYPE_SEQ</span><span class="special">(</span><span class="identifier">tpArray</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_IDENTITY_RESULT</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_IIF</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_IS_SEQ</span><span class="special">(</span><span class="identifier">tpArray</span><span class="special">),</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_IDENTITY</span><span class="special">(</span><span class="identifier">SEQ</span><span class="special">),</span> <span class="special">\</span>
<span class="identifier">BOOST_TTI_DETAIL_TRAIT_CALL_HAS_TEMPLATE_CHECK_PARAMS_TYPE_TUPLE</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">(</span><span class="identifier">tpArray</span><span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_TTI_DETAIL_TRAIT_CALL_HAS_TEMPLATE_CHECK_PARAMS_TYPE_TUPLE</span><span class="special">(</span><span class="identifier">tpArray</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_IDENTITY_RESULT</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_EXPR_IIF</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_IS_TUPLE</span><span class="special">(</span><span class="identifier">tpArray</span><span class="special">),</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_IDENTITY</span><span class="special">(</span><span class="identifier">TUPLE</span><span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_TTI_DETAIL_TRAIT_CALL_HAS_TEMPLATE_CHECK_PARAMS_TYPE_CONCAT</span><span class="special">(</span><span class="identifier">trait</span><span class="special">,</span><span class="identifier">name</span><span class="special">,</span><span class="identifier">tpArray</span><span class="special">,</span><span class="identifier">name</span><span class="special">)</span> <span class="special">\</span>
<span class="special">(</span> <span class="identifier">BOOST_PP_ADD</span><span class="special">(</span><span class="identifier">BOOST_PP_</span> <span class="special">##</span> <span class="identifier">name</span> <span class="special">##</span> <span class="identifier">_SIZE</span><span class="special">(</span><span class="identifier">tpArray</span><span class="special">),</span><span class="number">4</span><span class="special">),</span> <span class="special">(</span> <span class="identifier">trait</span><span class="special">,</span> <span class="identifier">name</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="keyword">false</span><span class="special">,</span> <span class="identifier">BOOST_PP_</span> <span class="special">##</span> <span class="identifier">name</span> <span class="special">##</span> <span class="identifier">_ENUM</span><span class="special">(</span><span class="identifier">tpArray</span><span class="special">)</span> <span class="special">)</span> <span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="preprocessor">#else</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_TTI_DETAIL_TRAIT_CALL_HAS_TEMPLATE_CHECK_PARAMS</span><span class="special">(</span><span class="identifier">trait</span><span class="special">,</span><span class="identifier">name</span><span class="special">,</span><span class="identifier">tpArray</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_TTI_DETAIL_HAS_MEMBER_WITH_TEMPLATE_SFINAE</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="special">(</span> <span class="identifier">BOOST_PP_ADD</span><span class="special">(</span><span class="identifier">BOOST_PP_ARRAY_SIZE</span><span class="special">(</span><span class="identifier">tpArray</span><span class="special">),</span><span class="number">4</span><span class="special">),</span> <span class="special">(</span> <span class="identifier">trait</span><span class="special">,</span> <span class="identifier">name</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="keyword">false</span><span class="special">,</span> <span class="identifier">BOOST_PP_ARRAY_ENUM</span><span class="special">(</span><span class="identifier">tpArray</span><span class="special">)</span> <span class="special">)</span> <span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="preprocessor">#endif</span>
</pre>
<p>
This of course gets more elaborate, but could be shortened considerably if
we chose to use BOOST_VMD_GET_TYPE and the invented BOOST_VMD_SWITCH of our
first example. We will assume in this second version of the code above that
our BOOST_VMD_SWITCH macro has been #included from somewhere.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">arithmetic</span><span class="special">/</span><span class="identifier">add</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">array</span><span class="special">/</span><span class="keyword">enum</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">array</span><span class="special">/</span><span class="identifier">size</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">list</span><span class="special">/</span><span class="keyword">enum</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">list</span><span class="special">/</span><span class="identifier">size</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">seq</span><span class="special">/</span><span class="keyword">enum</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">seq</span><span class="special">/</span><span class="identifier">size</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">tuple</span><span class="special">/</span><span class="keyword">enum</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">tuple</span><span class="special">/</span><span class="identifier">size</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">get_type</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#if</span> <span class="identifier">BOOST_PP_VARIADICS</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_TTI_DETAIL_TRAIT_CALL_HAS_TEMPLATE_CHECK_PARAMS</span><span class="special">(</span><span class="identifier">trait</span><span class="special">,</span><span class="identifier">name</span><span class="special">,</span><span class="identifier">tpArray</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_TTI_DETAIL_HAS_MEMBER_WITH_TEMPLATE_SFINAE</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_TTI_DETAIL_TRAIT_CALL_HAS_TEMPLATE_CHECK_PARAMS_TYPE_CONCAT</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">trait</span><span class="special">,</span><span class="identifier">name</span><span class="special">,</span><span class="identifier">tpArray</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_SWITCH</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">tpArray</span><span class="special">),</span> <span class="special">\</span>
<span class="special">(</span><span class="number">1</span><span class="special">),</span> <span class="special">\</span>
<span class="special">(</span><span class="identifier">BOOST_VMD_TYPE_ARRAY</span><span class="special">,</span><span class="identifier">BOOST_VMD_SWITCH_IDENTITY</span><span class="special">(</span><span class="identifier">ARRAY</span><span class="special">)),</span> <span class="special">\</span>
<span class="special">(</span><span class="identifier">BOOST_VMD_TYPE_LIST</span><span class="special">,</span><span class="identifier">BOOST_VMD_SWITCH_IDENTITY</span><span class="special">(</span><span class="identifier">LIST</span><span class="special">)),</span> <span class="special">\</span>
<span class="special">(</span><span class="identifier">BOOST_VMD_TYPE_SEQ</span><span class="special">,</span><span class="identifier">BOOST_VMD_SWITCH_IDENTITY</span><span class="special">(</span><span class="identifier">SEQ</span><span class="special">)),</span> <span class="special">\</span>
<span class="special">(</span><span class="identifier">BOOST_VMD_TYPE_TUPLE</span><span class="special">,</span><span class="identifier">BOOST_VMD_SWITCH_IDENTITY</span><span class="special">(</span><span class="identifier">TUPLE</span><span class="special">))</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_TTI_DETAIL_TRAIT_CALL_HAS_TEMPLATE_CHECK_PARAMS_TYPE_CONCAT</span><span class="special">(</span><span class="identifier">trait</span><span class="special">,</span><span class="identifier">name</span><span class="special">,</span><span class="identifier">tpArray</span><span class="special">,</span><span class="identifier">name</span><span class="special">)</span> <span class="special">\</span>
<span class="special">(</span> <span class="identifier">BOOST_PP_ADD</span><span class="special">(</span><span class="identifier">BOOST_PP_</span> <span class="special">##</span> <span class="identifier">name</span> <span class="special">##</span> <span class="identifier">_SIZE</span><span class="special">(</span><span class="identifier">tpArray</span><span class="special">),</span><span class="number">4</span><span class="special">),</span> <span class="special">(</span> <span class="identifier">trait</span><span class="special">,</span> <span class="identifier">name</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="keyword">false</span><span class="special">,</span> <span class="identifier">BOOST_PP_</span> <span class="special">##</span> <span class="identifier">name</span> <span class="special">##</span> <span class="identifier">_ENUM</span><span class="special">(</span><span class="identifier">tpArray</span><span class="special">)</span> <span class="special">)</span> <span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="preprocessor">#else</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_TTI_DETAIL_TRAIT_CALL_HAS_TEMPLATE_CHECK_PARAMS</span><span class="special">(</span><span class="identifier">trait</span><span class="special">,</span><span class="identifier">name</span><span class="special">,</span><span class="identifier">tpArray</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_TTI_DETAIL_HAS_MEMBER_WITH_TEMPLATE_SFINAE</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="special">(</span> <span class="identifier">BOOST_PP_ADD</span><span class="special">(</span><span class="identifier">BOOST_PP_ARRAY_SIZE</span><span class="special">(</span><span class="identifier">tpArray</span><span class="special">),</span><span class="number">4</span><span class="special">),</span> <span class="special">(</span> <span class="identifier">trait</span><span class="special">,</span> <span class="identifier">name</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="keyword">false</span><span class="special">,</span> <span class="identifier">BOOST_PP_ARRAY_ENUM</span><span class="special">(</span><span class="identifier">tpArray</span><span class="special">)</span> <span class="special">)</span> <span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="comment">/**/</span>
<span class="preprocessor">#endif</span>
</pre>
<p>
This is shorter and easier to understand. The '(1)' passed as the calling values
to BOOST_VMD_SWITCH could just as well be '()' but VC8 has trouble with empty
parentheses so I avoid it here.
</p>
<p>
In the case of the TTI, is such a change worth it to give more flexibility
to the end-user ? In reality, because the variadic version of passing the specific
template parameters as variadic data is syntactically easier to use than any
of the Boost PP composite forms, I am actually happy enough with that use not
to pursue the sort of functionality I presented in this example. But the example
nonetheless shows the power of the VMD functionality for creating macros which
add flexibility when the macro programmer feels he needs it for his library.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_conv.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../variadic_macro_data_reference.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,510 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Generic macros for working with data types</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="prev" href="vmd_specific/vmd_identifying.html" title="Identifying data types">
<link rel="next" href="vmd_generic/vmd_convert_sequence.html" title="Getting the type of data">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_specific/vmd_identifying.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_generic/vmd_convert_sequence.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="variadic_macro_data.vmd_generic"></a><a class="link" href="vmd_generic.html" title="Generic macros for working with data types">Generic macros for working
with data types</a>
</h2></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="vmd_generic.html#variadic_macro_data.vmd_generic.vmd_sequence">Parsing
sequences</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="vmd_generic.html#variadic_macro_data.vmd_generic.vmd_sequence.vmd_sequence_convert">Converting
sequences</a></span></dt>
<dt><span class="section"><a href="vmd_generic.html#variadic_macro_data.vmd_generic.vmd_sequence.vmd_sequence_access">Accessing
a sequence element</a></span></dt>
</dl></dd>
<dt><span class="section"><a href="vmd_generic/vmd_convert_sequence.html">Getting
the type of data</a></span></dt>
<dt><span class="section"><a href="vmd_generic/vmd_assert.html">Testing for
equality and inequality</a></span></dt>
</dl></div>
<p>
Besides the specific macros for working with data types VMD has a number of
generic macros for parsing sequences.
</p>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="variadic_macro_data.vmd_generic.vmd_sequence"></a><a class="link" href="vmd_generic.html#variadic_macro_data.vmd_generic.vmd_sequence" title="Parsing sequences">Parsing
sequences</a>
</h3></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="vmd_generic.html#variadic_macro_data.vmd_generic.vmd_sequence.vmd_sequence_convert">Converting
sequences</a></span></dt>
<dt><span class="section"><a href="vmd_generic.html#variadic_macro_data.vmd_generic.vmd_sequence.vmd_sequence_access">Accessing
a sequence element</a></span></dt>
</dl></div>
<p>
In the normal use of Boost PP data is passed as arguments to a macro in discrete
units so that each parameter expects a single data type. A typical macro
might be:
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">AMACRO</span><span class="special">(</span><span class="identifier">anumber</span><span class="special">,</span><span class="identifier">atuple</span><span class="special">,</span><span class="identifier">anidentifier</span><span class="special">)</span> <span class="identifier">someoutput</span>
</pre>
<p>
where the 'atuple', having the form of ( data1, data2, data3 ), itself may
contain different data types of elements.
</p>
<p>
This is the standard macro design and internally it is the easiest way to
pass macro data back and forth. The Boost PP library has a rich set of functionality
to deal with all of its high-level data types, and variadic data, with its
own simpler functionality, also offers another alternative to representing
data.
</p>
<p>
Occasionally designers of macros, especially for the use of others programmers
within a particular library, have expressed the need for a macro parameter
to allow a more C/C++ like syntax where a single parameter might mimic a
C++ function-call or a C-like type modification syntax, or some other more
complicated construct. Something along the lines of:
</p>
<pre class="programlisting"><span class="identifier">areturn</span> <span class="identifier">afunction</span> <span class="special">(</span> <span class="identifier">aparameter1</span><span class="special">,</span> <span class="identifier">aparameter2</span><span class="special">,</span> <span class="identifier">aparameter3</span> <span class="special">)</span>
</pre>
<p>
or
</p>
<pre class="programlisting"><span class="special">(</span> <span class="identifier">type</span> <span class="special">)</span> <span class="identifier">data</span>
</pre>
<p>
etc. etc.
</p>
<p>
In other words, from a syntactical level when designing possible macro input,
is it possible to design parameter data to look more like C/C++ when macros
are used in a library and still do a certain amount of preprocessor metaprogramming
with such mixed token input ?
</p>
<p>
VMD has functionality which allows more than one type of preprocessing token,
excluding an 'empty' token which always refers to some entire input, to be
part of a single parameter of input data. These preprocessing tokens as a
single parameter are syntactically a consecutive series of data. The single
limitation of this consecutive series of data is that each top-level part
of the data of this series is of some VMD data type. What this means is that
if some input consists of a series of data types it is possible to extract
the data for each data type in that series.
</p>
<p>
In practicality what this means is that, given the examples just above, if
'areturn', 'afunction', and 'data' are identifiers it would be possible to
parse either of the two inputs above so that one could identify the different
data types involved and do preprocessor metaprogramming based on those results.
</p>
<h5>
<a name="variadic_macro_data.vmd_generic.vmd_sequence.h0"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_generic.vmd_sequence.sequence_definition"></a></span><a class="link" href="vmd_generic.html#variadic_macro_data.vmd_generic.vmd_sequence.sequence_definition">Sequence
definition</a>
</h5>
<p>
I will be calling such input data, which consists of all top-level data types
in a series, by the term of a 'sequence'. Each separate data type in the
sequence is called an 'element'. In this definition of a 'sequence' we can
have 0 or more elements, so that a sequence is a general name for any VMD
input. A sequence is therefore any input VMD can parse, whether it is emptiness,
a single element, or more than one element in a series. Therefore when we
speak of VMD macros parsing input data we are really speaking of VMD macros
parsing a sequence. A sequence can therefore also be part of a Boost PP composite
data type, or variadic data, and VMD can still parse such an embedded sequence
if asked to do so.
</p>
<h5>
<a name="variadic_macro_data.vmd_generic.vmd_sequence.h1"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_generic.vmd_sequence.sequence_parsing"></a></span><a class="link" href="vmd_generic.html#variadic_macro_data.vmd_generic.vmd_sequence.sequence_parsing">Sequence
parsing</a>
</h5>
<p>
Parsing a sequence means that VMD can step through each element of a sequence
sequentially, determine the type and data of each element, then move on to
the next element. Parsing is sequential and can only be done in a forward
direction, but it can be done any number of times. In C++ iterator terms
parsing of a sequence is a forward iterator.
</p>
<p>
Working with a sequence is equivalent to using VMD macros 'generically'.
</p>
<p>
Before I give an explanation of how to use a sequence using VMD generic functionality
I would like to make two points:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
The possibility of working with a sequence which contains more than one
data type can be easily abused. In general keeping things simple is usually
better than making things overly complicated when it comes to the syntactical
side of things in a computer language. A macro parameter syntactical
possibility has to be understandable to be used.
</li>
<li class="listitem">
Using VMD to parse the individual data types of a sequence takes more
preprocessing time than functionality offered with Boost PP data types,
because it is based on forward access through each top-level type of
the sequence.
</li>
</ul></div>
<p>
The one constraint in a sequence is that the top-level must consist of VMD
data types, in other words preprocessor tokens which VMD understands. By
top-level it is meant that a Boost PP composite data may have elements which
VMD cannot parse but as long as the input consists of the composite data
types and not the inner unparsable elements, VMD can parse the input. Therefore
if preprocessor data is one of the examples above, you will be successful
in using VMD. However if your preprocessor data takes the form of:
</p>
<pre class="programlisting"><span class="special">&amp;</span><span class="identifier">name</span> <span class="identifier">identifier</span> <span class="special">(</span> <span class="identifier">param</span> <span class="special">)</span>
</pre>
<p>
or
</p>
<pre class="programlisting"><span class="identifier">identifier</span> <span class="string">"string literal"</span>
</pre>
<p>
or
</p>
<pre class="programlisting"><span class="identifier">identifier</span> <span class="special">+</span> <span class="identifier">number</span>
</pre>
<p>
or
</p>
<pre class="programlisting"><span class="identifier">identifier</span> <span class="special">+=</span> <span class="number">4.3</span>
</pre>
<p>
etc. etc.
</p>
<p>
you will not be able to parse the data using VMD since '&amp;', "string
literal", '+', '+=', and "4.3" are preprocessor tokens which
are not VMD top-level data types and therefore VMD cannot handle them at
the parsing level. You can still of course pass such data as preprocessing
input to macros but you cannot use VMD to recognize the parts of such data.
</p>
<p>
This is similar to the fact that VMD cannot tell you what type preprocessor
data is as a whole, using any of the VMD identifying macros already discussed,
if the type is not one that VMD can handle.
</p>
<p>
On the other hand you can still use VMD to parse such tokens in the input
if you use Boost PP data types as top-level data types to do so. Such as:
</p>
<pre class="programlisting"><span class="special">(</span> <span class="special">&amp;</span><span class="identifier">name</span> <span class="special">)</span> <span class="identifier">identifier</span> <span class="special">(</span> <span class="identifier">param</span> <span class="special">)</span>
</pre>
<p>
or
</p>
<pre class="programlisting"><span class="identifier">identifier</span> <span class="special">(</span> <span class="string">"string literal"</span> <span class="special">)</span>
</pre>
<p>
or
</p>
<pre class="programlisting"><span class="identifier">identifier</span> <span class="special">(</span> <span class="special">+</span> <span class="special">)</span> <span class="identifier">number</span>
</pre>
<p>
or
</p>
<pre class="programlisting"><span class="identifier">identifier</span> <span class="special">(</span> <span class="special">+=</span> <span class="special">)</span> <span class="number">4</span> <span class="special">(</span> <span class="special">.</span> <span class="special">)</span> <span class="number">3</span>
</pre>
<p>
The succeeding topics explain the VMD functionality for parsing a sequence
for each individual VMD data type in that sequence.
</p>
<h5>
<a name="variadic_macro_data.vmd_generic.vmd_sequence.h2"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_generic.vmd_sequence.sequence_types"></a></span><a class="link" href="vmd_generic.html#variadic_macro_data.vmd_generic.vmd_sequence.sequence_types">Sequence
types</a>
</h5>
<p>
A VMD sequence can be seen as one of either three general types:
</p>
<div class="orderedlist"><ol class="orderedlist" type="1">
<li class="listitem">
An empty sequence
</li>
<li class="listitem">
A single element sequence
</li>
<li class="listitem">
A multi-element sequence
</li>
</ol></div>
<p>
An empty sequence is merely input that is empty, what VMD calls "emptiness".
Use the previously explained BOOST_VMD_IS_EMPTY macro to test for an empty
sequence.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_empty</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">AN_EMPTY_SEQUENCE</span>
<span class="identifier">BOOST_VMD_IS_EMPTY</span><span class="special">(</span><span class="identifier">AN_EMPTY_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
</pre>
<p>
The type of an empty sequence is BOOST_VMD_TYPE_EMPTY.
</p>
<p>
A single element sequence is a single VMD data type. This is what we have
been previously discussing as data which VMD can parse in this documentation
with our identifying macros. You can use the BOOST_VMD_IS_UNARY macro to
test for a single element sequence.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_unary</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">A_SINGLE_ELEMENT_SEQUENCE</span> <span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">)</span>
<span class="identifier">BOOST_VMD_IS_UNARY</span><span class="special">(</span><span class="identifier">A_SINGLE_ELEMENT_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
</pre>
<p>
The type of a single element sequence is the type of the individual data
type. In our example above the type of A_SINGLE_ELEMENT_SEQUENCE is BOOST_VMD_TYPE_TUPLE.
</p>
<p>
A multi-element sequence consists of more than one data type. This is the
"new" type which VMD can parse. You can use the BOOST_VMD_IS_MULTI
macro to test for a multi-element sequence.
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">A_MULTI_ELEMENT_SEQUENCE</span> <span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">)</span> <span class="special">(</span><span class="number">1</span><span class="special">)(</span><span class="number">2</span><span class="special">)</span> <span class="number">45</span>
</pre>
<p>
The A_MULTI_ELEMENT_SEQUENCE consists of a tuple followed by a seq followed
by a number.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_multi</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_VMD_IS_MULTI</span><span class="special">(</span><span class="identifier">A_MULTI_ELEMENT_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
</pre>
<p>
The type of a multi-element sequence is always BOOST_VMD_TYPE_SEQUENCE.
</p>
<p>
The type of a sequence can be obtained generically with the BOOST_VMD_GET_TYPE
macro. We will be explaining this further in the documentation.
</p>
<h5>
<a name="variadic_macro_data.vmd_generic.vmd_sequence.h3"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_generic.vmd_sequence.sequence_size"></a></span><a class="link" href="vmd_generic.html#variadic_macro_data.vmd_generic.vmd_sequence.sequence_size">Sequence
size</a>
</h5>
<p>
The size of any sequence can be accessed using the BOOST_VMD_SIZE macro.
For an empty sequence the size is always 0. For a single element sequence
the size is always 1. For a multi-element sequence the size is the number
of individual top-level data types in the sequence.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">size</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_VMD_SIZE</span><span class="special">(</span><span class="identifier">AN_EMPTY_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span>
<span class="identifier">BOOST_VMD_SIZE</span><span class="special">(</span><span class="identifier">A_SINGLE_ELEMENT_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_SIZE</span><span class="special">(</span><span class="identifier">A_MULTI_ELEMENT_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">3</span>
</pre>
<h5>
<a name="variadic_macro_data.vmd_generic.vmd_sequence.h4"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_generic.vmd_sequence.using_vmd_to_parse_sequence_inpu"></a></span><a class="link" href="vmd_generic.html#variadic_macro_data.vmd_generic.vmd_sequence.using_vmd_to_parse_sequence_inpu">Using
VMD to parse sequence input</a>
</h5>
<p>
For a VMD sequence essentially two ways of parsing into individual data types
are offered by the VMD library:
</p>
<div class="orderedlist"><ol class="orderedlist" type="1">
<li class="listitem">
The sequence can be converted to any of the Boost PP data types, or to
variadic data, where each individual data type in the sequence becomes
a separate element of the particular composite data type chosen. The
conversion to a particular Boost PP data type or variadic data is slow,
because it is based on forward access through each top-level type of
the sequence, but afterwards accessing any individual element is as fast
as accessing any element in the Boost PP data type or among variadic
data.
</li>
<li class="listitem">
The sequence can be accessed directly through its individual elements.
This is slower than accessing an element of a Boost PP data type or variadic
data but offers conceptual access to the original sequence as a series
of elements.
</li>
</ol></div>
<p>
These two techniques will be discussed in succeeding topics.
</p>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="variadic_macro_data.vmd_generic.vmd_sequence.vmd_sequence_convert"></a><a class="link" href="vmd_generic.html#variadic_macro_data.vmd_generic.vmd_sequence.vmd_sequence_convert" title="Converting sequences">Converting
sequences</a>
</h4></div></div></div>
<p>
The easiest way to work with a sequence is to convert it to a Boost PP
data type. Likewise you can also convert a sequence to variadic data even
though the Boost PP data types have much greater functionality than variadic
data in Boost PP.
</p>
<p>
To convert a sequence to a Boost PP data type or variadic data the macros
to be used are:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
BOOST_VMD_TO_ARRAY(sequence) to convert the sequence to an array
</li>
<li class="listitem">
BOOST_VMD_TO_LIST(sequence) to convert the sequence to a list
</li>
<li class="listitem">
BOOST_VMD_TO_SEQ(sequence) to convert the sequence to a seq
</li>
<li class="listitem">
BOOST_VMD_TO_TUPLE(sequence) to convert the sequence to a tuple
</li>
<li class="listitem">
BOOST_VMD_ENUM(sequence) to convert the sequence to variadic data
</li>
</ul></div>
<p>
After the conversion the elements of a sequence become the elements of
the corresponding composite data type.
</p>
<p>
Once the elements of the sequence have been converted to the elements of
the composite data type the full power of that composite data type can
be used to process each element. Furthermore the programmer can use VMD
to discover the type of an individual element for further processing.
</p>
<p>
For single element sequences the result is always a single element composite
data type. For multi-element sequences the result is always a composite
data type of more than one element.
</p>
<p>
For a sequence that is empty the result is emptiness when converting to
a seq, tuple, or variadic data; the result is an empty array or list when
converting to each of those composite data types respectively.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="keyword">enum</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">to_array</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">to_list</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">to_seq</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">to_tuple</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_ANID</span> <span class="special">(</span><span class="identifier">ANID</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_EMPTY</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_SINGLE</span> <span class="number">35</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_SINGLE_2</span> <span class="identifier">ANID</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_MULTI</span> <span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="number">1</span><span class="special">)</span> <span class="special">(</span><span class="number">2</span><span class="special">)(</span><span class="number">3</span><span class="special">)(</span><span class="number">4</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_MULTI_2</span> <span class="identifier">BOOST_VMD_TYPE_SEQ</span> <span class="special">(</span><span class="number">2</span><span class="special">,(</span><span class="number">5</span><span class="special">,</span><span class="number">6</span><span class="special">))</span>
<span class="identifier">BOOST_VMD_TO_ARRAY</span><span class="special">(</span><span class="identifier">SEQUENCE_EMPTY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">an</span> <span class="identifier">empty</span> <span class="identifier">array</span> <span class="char">'(0,())'</span>
<span class="identifier">BOOST_VMD_TO_LIST</span><span class="special">(</span><span class="identifier">SEQUENCE_SINGLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">a</span> <span class="identifier">one</span><span class="special">-</span><span class="identifier">element</span> <span class="identifier">list</span> <span class="char">'(35,BOOST_PP_NIL)'</span>
<span class="identifier">BOOST_VMD_TO_SEQ</span><span class="special">(</span><span class="identifier">SEQUENCE_SINGLE_2</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">a</span> <span class="identifier">one</span><span class="special">-</span><span class="identifier">element</span> <span class="identifier">seq</span> <span class="char">'(ANID)'</span>
<span class="identifier">BOOST_VMD_TO_TUPLE</span><span class="special">(</span><span class="identifier">SEQUENCE_MULTI</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">a</span> <span class="identifier">multi</span><span class="special">-</span><span class="identifier">element</span> <span class="identifier">tuple</span> <span class="char">'((0,1),(2)(3)(4))'</span>
<span class="identifier">BOOST_VMD_ENUM</span><span class="special">(</span><span class="identifier">SEQUENCE_MULTI_2</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">multi</span><span class="special">-</span><span class="identifier">element</span> <span class="identifier">variadic</span> <span class="identifier">data</span> <span class="char">'BOOST_VMD_TYPE_SEQ,(2,(5,6))'</span>
</pre>
<h6>
<a name="variadic_macro_data.vmd_generic.vmd_sequence.vmd_sequence_convert.h0"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_generic.vmd_sequence.vmd_sequence_convert.usage"></a></span><a class="link" href="vmd_generic.html#variadic_macro_data.vmd_generic.vmd_sequence.vmd_sequence_convert.usage">Usage</a>
</h6>
<p>
You can use the general header file:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<p>
or you can use individual header files for each of these macros. The individual
header files are:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">to_array</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// for the BOOST_VMD_TO_ARRAY macro</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">to_list</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// for the BOOST_VMD_TO_LIST macro</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">to_seq</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// for the BOOST_VMD_TO_SEQ macro</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">to_tuple</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// for the BOOST_VMD_TO_TUPLE macro.</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="keyword">enum</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// for the BOOST_VMD_ENUM macro.</span>
</pre>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="variadic_macro_data.vmd_generic.vmd_sequence.vmd_sequence_access"></a><a class="link" href="vmd_generic.html#variadic_macro_data.vmd_generic.vmd_sequence.vmd_sequence_access" title="Accessing a sequence element">Accessing
a sequence element</a>
</h4></div></div></div>
<p>
It is possible to access an individual element of a sequence. The macro
to do this is called BOOST_VMD_ELEM. The macro takes two required parameters.
The required parameters are the element number to access and the sequence,
in that order. The element number is a 0-based number and its maximum value
should be one less than the size of the sequence.
</p>
<p>
The BOOST_VMD_ELEM macro returns the actual sequence element. If the first
required parameter is greater or equal to the size of the sequence the
macro returns emptiness. Because of this using BOOST_VMD_ELEM on an empty
sequence, whose size is 0, always returns emptiness.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">elem</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_ANAME</span> <span class="special">(</span><span class="identifier">ANAME</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE</span> <span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">,</span><span class="number">3</span><span class="special">)</span> <span class="number">46</span> <span class="special">(</span><span class="identifier">list_data1</span><span class="special">,(</span><span class="identifier">list_data2</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">))</span> <span class="identifier">BOOST_VMD_TYPE_SEQ</span> <span class="identifier">ANAME</span>
<span class="preprocessor">#define</span> <span class="identifier">AN_EMPTY_SEQUENCE</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">,</span><span class="number">3</span><span class="special">)</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">46</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">2</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="special">(</span><span class="identifier">list_data1</span><span class="special">,(</span><span class="identifier">list_data2</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">))</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">3</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_SEQ</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">4</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">ANAME</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">5</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">emptiness</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">AN_EMPTY_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">emptiness</span>
</pre>
<p>
Accessing an element of a sequence directly is slower than accessing an
element of a Boost PP data type or even variadic data, since each access
has to directly cycle through each element of the sequence to get to the
one being accessed. The process of sequentially parsing each element again
each time is slower than accessing a Boost PP data type element.
</p>
<h6>
<a name="variadic_macro_data.vmd_generic.vmd_sequence.vmd_sequence_access.h0"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_generic.vmd_sequence.vmd_sequence_access.usage"></a></span><a class="link" href="vmd_generic.html#variadic_macro_data.vmd_generic.vmd_sequence.vmd_sequence_access.usage">Usage</a>
</h6>
<p>
You can use the general header file:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<p>
or you can use the individual header file:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">elem</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
</div>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_specific/vmd_identifying.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_generic/vmd_convert_sequence.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,254 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Testing for equality and inequality</title>
<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../vmd_generic.html" title="Generic macros for working with data types">
<link rel="prev" href="vmd_convert_sequence.html" title="Getting the type of data">
<link rel="next" href="../vmd_modifiers.html" title="Macros with modifiers">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_convert_sequence.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_generic.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../vmd_modifiers.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="variadic_macro_data.vmd_generic.vmd_assert"></a><a class="link" href="vmd_assert.html" title="Testing for equality and inequality">Testing for
equality and inequality</a>
</h3></div></div></div>
<p>
VMD allows the programmer to test generically for the equality or inequality
of any value which VMD can parse. This includes emptiness, identifiers, numbers,
types, arrays, lists, seqs, tuples, and multi-element sequences.
</p>
<p>
The macro to test for equality is called BOOST_VMD_EQUAL and it has two required
parameters which are the two values against which to test. The values can
be any VMD data type.
</p>
<p>
For the composite data types of array, list, seq, and tuple, or any of those
types in a multi-element sequence, the elements of those types must also
be a data type which VMD can parse. BOOST_VMD_EQUAL recursively parses the
elements in a composite data type for equality, up to a level of 16 inner
types, to test that one composite type equals another composite type. The
requirement, that composite elements must also be a data type which VMD can
parse, is different from most other macros in the VMD library, where only
the top-level composite type need be parsed enough to determine the type
of the data. If BOOST_VMD_EQUAL encounters a data type which it cannot parse
the result will be UB.
</p>
<p>
VMD identifiers used in equality testing must be registered and pre-detected.
All numbers and v-types are already registered/pre-detected for equality
testing so it is only user-defined identifiers which must be registered and
pre-detected. If an identifier has not been both registered and predetected
it will never be equal to the same identifier value, so it will always fail
equality testing, although it will not give a preprocessing error doing so.
</p>
<p>
The BOOST_VMD_EQUAL macro returns 1 if both parameters are equal and 0 if
the parameters are not equal.
</p>
<p>
Conversely to test for inequality, of the same values as are required in
testing for equality, the VMD library has the macro BOOST_VMD_NOT_EQUAL.
This macro is simply a complement of the BOOST_VMD_EQUAL macro. If BOOST_VMD_EQUAL
returns 1 then BOOST_VMD_NOT_EQUAL returns 0 and if BOOST_VMD_EQUAL returns
0 then BOOST_VMD_NOT_EQUAL returns 1.
</p>
<p>
The BOOST_VMD_EQUAL and BOOST_VMD_NOT_EQUAL macros are called "equality
macros".
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">equal</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_AN_ID1</span> <span class="special">(</span><span class="identifier">AN_ID1</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_AN_ID2</span> <span class="special">(</span><span class="identifier">AN_ID2</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_AN_ID1_AN_ID1</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_AN_ID2_AN_ID2</span>
<span class="preprocessor">#define</span> <span class="identifier">AN_IDENTIFIER1</span> <span class="identifier">AN_ID1</span>
<span class="preprocessor">#define</span> <span class="identifier">AN_IDENTIFIER2</span> <span class="identifier">AN_ID2</span>
<span class="preprocessor">#define</span> <span class="identifier">AN_IDENTIFIER3</span> <span class="identifier">AN_ID1</span> <span class="comment">// same as AN_IDENTIFIER1 = AN_ID1</span>
<span class="preprocessor">#define</span> <span class="identifier">A_NUMBER1</span> <span class="number">33</span>
<span class="preprocessor">#define</span> <span class="identifier">A_NUMBER2</span> <span class="number">145</span>
<span class="preprocessor">#define</span> <span class="identifier">A_NUMBER3</span> <span class="number">33</span> <span class="comment">// same as A_NUMBER1 = 33</span>
<span class="preprocessor">#define</span> <span class="identifier">A_TUPLE1</span> <span class="special">(</span><span class="identifier">AN_IDENTIFIER1</span><span class="special">,</span><span class="identifier">A_NUMBER1</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">A_TUPLE2</span> <span class="special">(</span><span class="identifier">AN_IDENTIFIER1</span><span class="special">,</span><span class="identifier">A_NUMBER2</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">A_TUPLE3</span> <span class="special">(</span><span class="identifier">AN_IDENTIFIER3</span><span class="special">,</span><span class="identifier">A_NUMBER3</span><span class="special">)</span> <span class="comment">// same as A_TUPLE1 = (AN_ID1,33)</span>
<span class="preprocessor">#define</span> <span class="identifier">A_SEQ1</span> <span class="special">(</span><span class="identifier">A_NUMBER1</span><span class="special">)(</span><span class="identifier">A_TUPLE1</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">A_SEQ2</span> <span class="special">(</span><span class="identifier">A_NUMBER2</span><span class="special">)(</span><span class="identifier">A_TUPLE2</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">A_SEQ3</span> <span class="special">(</span><span class="identifier">A_NUMBER3</span><span class="special">)(</span><span class="identifier">A_TUPLE3</span><span class="special">)</span> <span class="comment">// same as A_SEQ1 = (33)((AN_ID1,33))</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">AN_IDENTIFIER1</span><span class="special">,</span><span class="identifier">AN_IDENTIFIER2</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">AN_IDENTIFIER1</span><span class="special">,</span><span class="identifier">AN_IDENTIFIER3</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_NUMBER1</span><span class="special">,</span><span class="identifier">A_NUMBER2</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_NUMBER1</span><span class="special">,</span><span class="identifier">A_NUMBER3</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_TUPLE1</span><span class="special">,</span><span class="identifier">A_TUPLE2</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_TUPLE1</span><span class="special">,</span><span class="identifier">A_TUPLE3</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_SEQ1</span><span class="special">,</span><span class="identifier">A_SEQ2</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_SEQ1</span><span class="special">,</span><span class="identifier">A_SEQ3</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
</pre>
<p>
When BOOST_VMD_EQUAL tests for equality it always parses data for their most
specific types. The reason for this is that a valid tuple, which is also
an invalid list or array, can never be compared completely because all elements
of that tuple are not data types which VMD can parse. Therefore VMD always
tests equality based on the most specific type for any value being tested,
which speeds up testing for the more specific tuple data types such as lists
and arrays.
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">TUPLE_IS_ARRAY1</span> <span class="special">(</span><span class="number">2</span><span class="special">,(</span><span class="number">3</span><span class="special">,</span><span class="number">4</span><span class="special">))</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE_IS_ARRAY2</span> <span class="special">(</span><span class="number">2</span><span class="special">,(</span><span class="number">4</span><span class="special">,</span><span class="number">5</span><span class="special">))</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE_IS_ARRAY3</span> <span class="special">(</span><span class="number">2</span><span class="special">,(</span><span class="number">3</span><span class="special">,</span><span class="number">4</span><span class="special">))</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE_IS_LIST1</span> <span class="special">(</span><span class="number">55</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE_IS_LIST2</span> <span class="special">(</span><span class="number">135</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE_IS_LIST3</span> <span class="special">(</span><span class="number">55</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE_IS_LIST_OR_ARRAY1</span> <span class="special">(</span><span class="number">2</span><span class="special">,(</span><span class="number">3</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">))</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE_IS_LIST_OR_ARRAY2</span> <span class="special">(</span><span class="number">2</span><span class="special">,(</span><span class="number">4</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">))</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE_IS_LIST_OR_ARRAY3</span> <span class="special">(</span><span class="number">2</span><span class="special">,(</span><span class="number">3</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">))</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE_BUT_INVALID_ARRAY1</span> <span class="special">(&amp;</span><span class="number">2</span><span class="special">,(</span><span class="number">3</span><span class="special">,</span><span class="number">4</span><span class="special">))</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE_BUT_INVALID_ARRAY2</span> <span class="special">(&amp;</span><span class="number">2</span><span class="special">,(</span><span class="number">4</span><span class="special">,</span><span class="number">4</span><span class="special">))</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE_BUT_INVALID_ARRAY3</span> <span class="special">(&amp;</span><span class="number">2</span><span class="special">,(</span><span class="number">3</span><span class="special">,</span><span class="number">4</span><span class="special">))</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE_BUT_INVALID_LIST1</span> <span class="special">(</span><span class="number">55</span><span class="special">,^</span><span class="identifier">BOOST_PP_NIL</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE_BUT_INVALID_LIST2</span> <span class="special">(</span><span class="number">135</span><span class="special">,^</span><span class="identifier">BOOST_PP_NIL</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE_BUT_INVALID_LIST3</span> <span class="special">(</span><span class="number">55</span><span class="special">,^</span><span class="identifier">BOOST_PP_NIL</span><span class="special">)</span>
</pre>
<p>
All of the constructs above are valid tuples.
</p>
<p>
The first three are valid arrays, so they will be parsed and compared as
arrays, so that they can be used as in:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">equal</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">TUPLE_IS_ARRAY1</span><span class="special">,</span><span class="identifier">TUPLE_IS_ARRAY2</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">TUPLE_IS_ARRAY1</span><span class="special">,</span><span class="identifier">TUPLE_IS_ARRAY3</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
</pre>
<p>
The next three are valid lists, so they will be parsed and compared as lists,
so that they can be used as in:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">equal</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">TUPLE_IS_LIST1</span><span class="special">,</span><span class="identifier">TUPLE_IS_LIST2</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">TUPLE_IS_LIST1</span><span class="special">,</span><span class="identifier">TUPLE_IS_LIST3</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
</pre>
<p>
The next three are valid lists or arrays but will be parsed as lists because
lists are more specific than arrays. They can be used as in:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">equal</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">TUPLE_IS_LIST_OR_ARRAY1</span><span class="special">,</span><span class="identifier">TUPLE_IS_LIST_OR_ARRAY2</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">TUPLE_IS_LIST_OR_ARRAY1</span><span class="special">,</span><span class="identifier">TUPLE_IS_LIST_OR_ARRAY3</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
</pre>
<p>
The next three are valid tuples but invalid arrays. The BOOST_VMD_EQUAL macro
attempts to parse them as the most specific type they can be, which is an
array. But the attempt to parse them as arrays will lead to UB because the
number which signifies the size of the array is invalid as a number. Now
let us suppose we should parse them as the less specific type of a tuple
instead of as an array. This will still give UB if we will attempt to compare
the first tuple element against a corresponding first tuple element of another
tuple, and when we do will again encounter UB because it is not a data type
VMD can parse.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">equal</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">TUPLE_BUT_INVALID_ARRAY1</span><span class="special">,</span><span class="identifier">TUPLE_BUT_INVALID_ARRAY1</span><span class="special">)</span> <span class="identifier">will</span> <span class="identifier">generate</span> <span class="identifier">UB</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">TUPLE_BUT_INVALID_ARRAY1</span><span class="special">,</span><span class="identifier">TUPLE_BUT_INVALID_ARRAY1</span><span class="special">)</span> <span class="identifier">will</span> <span class="identifier">generate</span> <span class="identifier">UB</span>
</pre>
<p>
The next three are valid tuples but invalid lists. The BOOST_VMD_EQUAL macro
attempts to parse them as the most specific type they can be, which is a
list. But the attempt to parse them as lists will lead to UB because the
identifier which signifies the end-of-list is invalid as an identifier. Now
let us suppose we should parse them as the less specific type of a tuple
instead of as a list. This will still give UB if we will attempt to compare
the second tuple element against a corresponding second tuple element of
another tuple, and when we do will again encounter UB because it is not a
data type VMD can parse.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">equal</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">TUPLE_BUT_INVALID_LIST1</span><span class="special">,</span><span class="identifier">TUPLE_BUT_INVALID_LIST2</span><span class="special">)</span> <span class="identifier">will</span> <span class="identifier">generate</span> <span class="identifier">UB</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">TUPLE_BUT_INVALID_LIST1</span><span class="special">,</span><span class="identifier">TUPLE_BUT_INVALID_LIST3</span><span class="special">)</span> <span class="identifier">will</span> <span class="identifier">generate</span> <span class="identifier">UB</span>
</pre>
<p>
It is possible that a composite data type which has an element which VMD
cannot parse will not give UB when compared for equality, but rather just
the test for equality will fail. This can occur if the algorithm which tests
for equality tests false before parsing of the particular element. Such a
situation might be:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">equal</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">A_TUPLE1</span> <span class="special">(</span><span class="number">3</span><span class="special">,</span><span class="number">4</span><span class="special">,</span><span class="string">"astring"</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">A_TUPLE2</span> <span class="special">(</span><span class="number">3</span><span class="special">,</span><span class="number">4</span><span class="special">)</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_TUPLE1</span><span class="special">,</span><span class="identifier">A_TUPLE2</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span> <span class="identifier">rather</span> <span class="identifier">than</span> <span class="identifier">generate</span> <span class="identifier">UB</span>
</pre>
<p>
The reason the above correctly returns 0, rather than generate UB when VMD
attempts to parse '"astring"', which is not a data type VMD can
parse, is because the algorithm for testing equality tests whether or not
the tuples have the same number of elements before it tests for the equality
of each element. This is just one example where testing for equality may
fail before UB is generated when BOOST_VMD_EQUAL attempts to parse a data
type which it cannot handle. Nevertheless the general rule should still be
considered that for BOOST_VMD_EQUAL/BOOT_VMD_NOT_EQUAL all data types, even
an element of a composite data type, must be a VMD data type if the macro
is to work properly, else UB could occur.
</p>
<h5>
<a name="variadic_macro_data.vmd_generic.vmd_assert.h0"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_generic.vmd_assert.usage"></a></span><a class="link" href="vmd_assert.html#variadic_macro_data.vmd_generic.vmd_assert.usage">Usage</a>
</h5>
<p>
You can use the general header file:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<p>
or you can use the individual header files:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">equal</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="keyword">for</span> <span class="identifier">the</span> <span class="identifier">BOOST_VMD_EQUAL</span> <span class="identifier">macro</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">not_equal</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="keyword">for</span> <span class="identifier">the</span> <span class="identifier">BOOST_VMD_NOT_EQUAL</span> <span class="identifier">macro</span>
</pre>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_convert_sequence.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_generic.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../vmd_modifiers.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,98 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Getting the type of data</title>
<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../vmd_generic.html" title="Generic macros for working with data types">
<link rel="prev" href="../vmd_generic.html" title="Generic macros for working with data types">
<link rel="next" href="vmd_assert.html" title="Testing for equality and inequality">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../vmd_generic.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_generic.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_assert.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="variadic_macro_data.vmd_generic.vmd_convert_sequence"></a><a class="link" href="vmd_convert_sequence.html" title="Getting the type of data">Getting
the type of data</a>
</h3></div></div></div>
<p>
VMD has the ability to retrieve the type of any data which it can parse,
which means any VMD sequence. The macro to do this is called BOOST_VMD_GET_TYPE
and it takes a single required parameter, which is a VMD sequence.
</p>
<p>
It returns one of the types previously discussed when introducing v-types
as an identifier subset. As explained previously in that topic a v-type is
fully recognized by VMD macros and can be part of a sequence and passed as
VMD data just like all the other data types VMD recognizes.
</p>
<p>
When BOOST_VMD_GET_TYPE returns the type of data it returns by default the
most specific type that the data can be. This means that non-empty lists
and arrays are returned as such, not as tuples, and numbers and types and
empty lists are returned as such, not as identifiers.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">get_type</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_ANID</span> <span class="special">(</span><span class="identifier">ANID</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_EMPTY</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_MULTI</span> <span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">,</span><span class="number">3</span><span class="special">)</span> <span class="number">88</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE1</span> <span class="special">(</span><span class="number">3</span><span class="special">,(</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">,</span><span class="number">3</span><span class="special">))</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE2</span> <span class="identifier">ANID</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE3</span> <span class="special">(</span><span class="number">1</span><span class="special">,(</span><span class="number">2</span><span class="special">,(</span><span class="number">3</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">)))</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE4</span> <span class="number">1</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE5</span> <span class="special">(</span><span class="number">1</span><span class="special">)(</span><span class="number">2</span><span class="special">)(</span><span class="number">3</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE6</span> <span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">,</span><span class="number">3</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE7</span> <span class="identifier">BOOST_VMD_TYPE_NUMBER</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">SEQUENCE_EMPTY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_EMPTY</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">SEQUENCE_MULTI</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_SEQUENCE</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">SEQUENCE1</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_ARRAY</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">SEQUENCE2</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">SEQUENCE3</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_LIST</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">SEQUENCE4</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_NUMBER</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">SEQUENCE5</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_SEQ</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">SEQUENCE6</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_TUPLE</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">SEQUENCE7</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_TYPE</span>
</pre>
<h5>
<a name="variadic_macro_data.vmd_generic.vmd_convert_sequence.h0"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_generic.vmd_convert_sequence.usage"></a></span><a class="link" href="vmd_convert_sequence.html#variadic_macro_data.vmd_generic.vmd_convert_sequence.usage">Usage</a>
</h5>
<p>
You can use the general header file:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<p>
or you can use the individual header file:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">get_type</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<p>
for the BOOST_VMD_GET_TYPE macro.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../vmd_generic.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_generic.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_assert.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,314 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>History</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="prev" href="vmd_compilers.html" title="Compilers">
<link rel="next" href="vmd_ack.html" title="Acknowledgements">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_compilers.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_ack.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="variadic_macro_data.vmd_history"></a><a class="link" href="vmd_history.html" title="History">History</a>
</h2></div></div></div>
<h4>
<a name="variadic_macro_data.vmd_history.h0"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_history.version_1_9_boost_1_60"></a></span><a class="link" href="vmd_history.html#variadic_macro_data.vmd_history.version_1_9_boost_1_60">Version 1.9,
Boost 1.60</a>
</h4>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
Added support for "empty" seqs and tuples
</li></ul></div>
<h4>
<a name="variadic_macro_data.vmd_history.h1"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_history.version_1_8"></a></span><a class="link" href="vmd_history.html#variadic_macro_data.vmd_history.version_1_8">Version
1.8</a>
</h4>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
After a review of VMD I have greatly simplified the main interfaces and
added optional functionality in the form of modifiers. The main changes
are the addition of the many generic macros for sequences and the expansions
of types to include the v-type.
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; ">
<li class="listitem">
Added BOOST_VMD_ELEM macro.
</li>
<li class="listitem">
Added BOOST_VMD_EQUAL macro.
</li>
<li class="listitem">
Added BOOST_VMD_NOT_EQUAL macro.
</li>
<li class="listitem">
Added BOOST_VMD_IS_MULTI macro.
</li>
<li class="listitem">
Added BOOST_VMD_IS_TYPE macro.
</li>
<li class="listitem">
Added BOOST_VMD_ASSERT_IS_TYPE macro.
</li>
<li class="listitem">
Added BOOST_VMD_IS_UNARY macro.
</li>
<li class="listitem">
Added BOOST_VMD_SIZE macro.
</li>
<li class="listitem">
Replaced with the BOOST_VMD_ELEM macro, using modifiers, a number
of macros which were eliminated. These are:
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: square; ">
<li class="listitem">
BOOST_VMD_IDENTIFER
</li>
<li class="listitem">
BOOST_VMD_BEGIN_IDENTIFIER
</li>
<li class="listitem">
BOOST_VMD_AFTER_IDENTIFIER
</li>
<li class="listitem">
BOOST_VMD_IS_BEGIN_IDENTIFIER
</li>
<li class="listitem">
BOOST_VMD_NUMBER
</li>
<li class="listitem">
BOOST_VMD_BEGIN_NUMBER
</li>
<li class="listitem">
BOOST_VMD_AFTER_NUMBER
</li>
<li class="listitem">
BOOST_VMD_IS_BEGIN_NUMBER
</li>
<li class="listitem">
BOOST_VMD_ARRAY
</li>
<li class="listitem">
BOOST_VMD_BEGIN_ARRAY
</li>
<li class="listitem">
BOOST_VMD_AFTER_ARRAY
</li>
<li class="listitem">
BOOST_VMD_IS_BEGIN_ARRAY
</li>
<li class="listitem">
BOOST_VMD_LIST
</li>
<li class="listitem">
BOOST_VMD_BEGIN_LIST
</li>
<li class="listitem">
BOOST_VMD_AFTER_LIST
</li>
<li class="listitem">
BOOST_VMD_IS_BEGIN_LIST
</li>
<li class="listitem">
BOOST_VMD_SEQ
</li>
<li class="listitem">
BOOST_VMD_BEGIN_SEQ
</li>
<li class="listitem">
BOOST_VMD_AFTER_SEQ
</li>
<li class="listitem">
BOOST_VMD_IS_BEGIN_SEQ
</li>
<li class="listitem">
BOOST_VMD_TUPLE
</li>
<li class="listitem">
BOOST_VMD_BEGIN_TUPLE
</li>
<li class="listitem">
BOOST_VMD_AFTER_TUPLE
</li>
<li class="listitem">
BOOST_VMD_IS_BEGIN_TUPLE
</li>
</ul></div>
</li>
<li class="listitem">
Every macro has its own header file.
</li>
</ul></div>
</li></ul></div>
<h4>
<a name="variadic_macro_data.vmd_history.h2"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_history.version_1_7"></a></span><a class="link" href="vmd_history.html#variadic_macro_data.vmd_history.version_1_7">Version
1.7</a>
</h4>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
The library has been reengineered to provide vastly added functionality.
This includes:
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; ">
<li class="listitem">
Adding functionality for parsing v-types.
</li>
<li class="listitem">
Adding functionality for parsing sequences of v-types.
</li>
<li class="listitem">
Adding improved ASSERT macros.
</li>
<li class="listitem">
Adding BOOST_VMD_EMPTY and BOOST_VMD_IDENTITY.
</li>
</ul></div>
</li></ul></div>
<h4>
<a name="variadic_macro_data.vmd_history.h3"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_history.version_1_6"></a></span><a class="link" href="vmd_history.html#variadic_macro_data.vmd_history.version_1_6">Version
1.6</a>
</h4>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
Stripped off all functionality duplicated by the variadic macro functionality
added to Boost PP.
</li>
<li class="listitem">
Removed the notion of 'native' and 'pplib' modes.
</li>
<li class="listitem">
Use the BOOST_PP_VARIADICS macro from the Boost PP library to determine
variadic macro availability and removed the native macro for determining
this from this library.
</li>
<li class="listitem">
Updated documentation, especially to give fuller information of the use
of the BOOST_VMD_EMPTY macro and its flaw and use with Visual C++.
</li>
<li class="listitem">
Changed the directory structure to adhere to the Modular Boost structure.
</li>
</ul></div>
<h4>
<a name="variadic_macro_data.vmd_history.h4"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_history.version_1_5"></a></span><a class="link" href="vmd_history.html#variadic_macro_data.vmd_history.version_1_5">Version
1.5</a>
</h4>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
Added macros for verifying Boost PP data types.
</li>
<li class="listitem">
Added macros for detecting and removing beginning parens.
</li>
<li class="listitem">
Added a macro for testing for the emptiness of a parameter.
</li>
<li class="listitem">
Added support for individual header files.
</li>
<li class="listitem">
Added support for 'native' and 'pplib' modes.
</li>
<li class="listitem">
Added control macros for controlling the variadic macro availability, mode,
and data verification.
</li>
</ul></div>
<h4>
<a name="variadic_macro_data.vmd_history.h5"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_history.version_1_4"></a></span><a class="link" href="vmd_history.html#variadic_macro_data.vmd_history.version_1_4">Version
1.4</a>
</h4>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
Removed internal dependency on BOOST_PP_CAT and BOOST_PP_ADD when using
VC++.
</li></ul></div>
<h4>
<a name="variadic_macro_data.vmd_history.h6"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_history.version_1_3"></a></span><a class="link" href="vmd_history.html#variadic_macro_data.vmd_history.version_1_3">Version
1.3</a>
</h4>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
Moved version information and history into the documentation.
</li>
<li class="listitem">
Separate files for build.txt in the doc sub-directory and readme.txt in
the top-level directory.
</li>
<li class="listitem">
Breaking changes
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; ">
<li class="listitem">
The name of the main header file is shortened to 'vmd.hpp'.
</li>
<li class="listitem">
The library follows the Boost conventions.
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: square; ">
<li class="listitem">
Changed the filenames to lower case and underscores.
</li>
<li class="listitem">
The macros now start with BOOST_VMD_ rather than just VMD_
as previously.
</li>
</ul></div>
</li>
</ul></div>
</li>
</ul></div>
<h4>
<a name="variadic_macro_data.vmd_history.h7"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_history.version_1_2"></a></span><a class="link" href="vmd_history.html#variadic_macro_data.vmd_history.version_1_2">Version
1.2</a>
</h4>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
Added a readme.txt file.
</li>
<li class="listitem">
Updated all jamfiles so that the library may be tested and docs generated
from its own local directory.
</li>
</ul></div>
<h4>
<a name="variadic_macro_data.vmd_history.h8"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_history.version_1_1"></a></span><a class="link" href="vmd_history.html#variadic_macro_data.vmd_history.version_1_1">Version
1.1</a>
</h4>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
Added better documentation for using variadic data with Boost PP and VMD.
</li></ul></div>
<h4>
<a name="variadic_macro_data.vmd_history.h9"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_history.version_1_0"></a></span><a class="link" href="vmd_history.html#variadic_macro_data.vmd_history.version_1_0">Version
1.0</a>
</h4>
<p>
Initial version of the library.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_compilers.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_ack.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,287 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Identifier subtypes</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="prev" href="vmd_modifiers/vmd_modifiers_single.html" title="Modifiers and the single-element sequence">
<link rel="next" href="vmd_useful.html" title="Useful variadic macros not in Boost PP">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_modifiers/vmd_modifiers_single.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_useful.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="variadic_macro_data.vmd_identifier_subtype"></a><a class="link" href="vmd_identifier_subtype.html" title="Identifier subtypes">Identifier
subtypes</a>
</h2></div></div></div>
<p>
Identifiers are the low-level data types which macro programmers use to pass
preprocessing data most often. As we have seen VMD has a system for registering
and detecting identifiers so that they can be parsed as part of preprocessor
data. This system also includes comparing identifiers for equality or inequality
using BOOST_VMD_EQUAL/BOOST_VMD_NOT_EQUAL and matching identifiers using identifier
modifiers in BOOST_VMD_IS_IDENTIFIER and BOOST_VMD_ELEM. Together these facilities
provide a rich set of functionality for handling identifiers in macros.
</p>
<p>
Both numbers and v-types are subtypes of identifiers, and can both be individually
recognized as data types of their own or worked with as identifiers using the
identifier facilities already mentioned. Numbers, in particular, also have
a rich set of functionality within the Boost PP library. As subtypes numbers
and v-types can be used as filter modifiers and can be returned as specific
types either when invoking BOOST_VMD_GET_TYPE or when using return type modifiers.
Furthermore VMD recognizes their individual v-types, BOOST_VMD_TYPE_NUMBER
and BOOST_VMD_TYPE_TYPE, as VMD data when parsing sequences.
</p>
<p>
It is possible for the end-user to define his own identifier subtype. This
is called a "user-defined subtype". Once a user-define subtype is
created all the generic type facilities of VMD which subtypes such as a number
or a v-type possess is automatically available for that user-defined subtype.
</p>
<h4>
<a name="variadic_macro_data.vmd_identifier_subtype.h0"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_identifier_subtype.defining_a_subtype"></a></span><a class="link" href="vmd_identifier_subtype.html#variadic_macro_data.vmd_identifier_subtype.defining_a_subtype">Defining
a subtype</a>
</h4>
<p>
In order to define a user-defined subtype a number of steps need to be followed.
These steps will be explained in detail further below:
</p>
<div class="orderedlist"><ol class="orderedlist" type="1">
<li class="listitem">
Register and pre-detect all identifiers of that subtype.
</li>
<li class="listitem">
Register and pre-detect a v-type name for that subtype.
</li>
<li class="listitem">
Subset register all identifiers of the subtype.
</li>
<li class="listitem">
Subset register the v-type name for the subtype.
</li>
</ol></div>
<p>
When we do the above, it is best to put all the macros in a single header file
and always include that header file when we work generically with our user-defined
subtype.
</p>
<h4>
<a name="variadic_macro_data.vmd_identifier_subtype.h1"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_identifier_subtype.register_and_pre_detect_all_iden"></a></span><a class="link" href="vmd_identifier_subtype.html#variadic_macro_data.vmd_identifier_subtype.register_and_pre_detect_all_iden">Register
and pre-detect all identifiers of that subtype</a>
</h4>
<p>
Registering and pre-detecting all of the identifiers of that subtype is exactly
the same as registering and pre-detecting any identifier.
</p>
<p>
Let's create some identifiers based for use in the mythical "udef"
library. We will put all our macros in the header file udef_vmd_macros.hpp.
</p>
<p>
We will need distinct names for the identifiers in our library, so we will
append UDEF_ to our identifier names to make them unique. Our udef library
deals in geometrical shapes so we will create a user-defined subtype which
consists of identifiers for the various shapes our udef library can manipulate
in their macros. So our identifier registrations and pre-detections placed
in our header file will be:
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_UDEF_CIRCLE</span> <span class="special">(</span><span class="identifier">UDEF_CIRCLE</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_UDEF_SQUARE</span> <span class="special">(</span><span class="identifier">UDEF_SQUARE</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_UDEF_TRIANGLE</span> <span class="special">(</span><span class="identifier">UDEF_TRIANGLE</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_UDEF_HEXAGON</span> <span class="special">(</span><span class="identifier">UDEF_HEXAGON</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_UDEF_CIRCLE_UDEF_CIRCLE</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_UDEF_SQUARE_UDEF_SQUARE</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_UDEF_TRIANGLE_UDEF_TRIANGLE</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_UDEF_HEXAGON_UDEF_HEXAGON</span>
</pre>
<h4>
<a name="variadic_macro_data.vmd_identifier_subtype.h2"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_identifier_subtype.register_and_pre_detect_a_v_type"></a></span><a class="link" href="vmd_identifier_subtype.html#variadic_macro_data.vmd_identifier_subtype.register_and_pre_detect_a_v_type">Register
and pre-detect a v-type name for that subtype</a>
</h4>
<p>
We need to create a unique v-type name for our user-defined subtype. The name
does not have to begin with BOOST_VMD_TYPE_ but it should be unique. Since
BOOST_VMD_TYPE_ is the common beginning of all v-types we will use it for consistency
but will append to it UDEF_SHAPES to give it a uniqueness which should not
be duplicated:
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_BOOST_VMD_TYPE_UDEF_SHAPES</span> <span class="special">(</span><span class="identifier">BOOST_VMD_TYPE_UDEF_SHAPES</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_BOOST_VMD_TYPE_UDEF_SHAPES_BOOST_VMD_TYPE_UDEF_SHAPES</span>
</pre>
<h4>
<a name="variadic_macro_data.vmd_identifier_subtype.h3"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_identifier_subtype.subtype_register_all_identifiers"></a></span><a class="link" href="vmd_identifier_subtype.html#variadic_macro_data.vmd_identifier_subtype.subtype_register_all_identifiers">Subtype
register all identifiers of the subtype</a>
</h4>
<p>
The macro to register an identifier subset starts with BOOST_VMD_SUBTYPE_REGISTER_
and you append to it each identifier in the subset. This is very much like
the way you use the BOOST_VMD_REGISTER_ macro. The difference is that unlike
the BOOST_VMD_REGISTER_ macro, which expands to a tuple whose single element
is the identifier, the BOOST_VMD_SUBTYPE_REGISTER_ expands to a tuple of two
elements where the first element is the subtype v-type and the second element
is the identifier.
</p>
<p>
For our udef user-defined subtype this would be:
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SUBTYPE_REGISTER_UDEF_CIRCLE</span> <span class="special">(</span><span class="identifier">BOOST_VMD_TYPE_UDEF_SHAPES</span><span class="special">,</span><span class="identifier">UDEF_CIRCLE</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SUBTYPE_REGISTER_UDEF_SQUARE</span> <span class="special">(</span><span class="identifier">BOOST_VMD_TYPE_UDEF_SHAPES</span><span class="special">,</span><span class="identifier">UDEF_SQUARE</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SUBTYPE_REGISTER_UDEF_TRIANGLE</span> <span class="special">(</span><span class="identifier">BOOST_VMD_TYPE_UDEF_SHAPES</span><span class="special">,</span><span class="identifier">UDEF_TRIANGLE</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SUBTYPE_REGISTER_UDEF_HEXAGON</span> <span class="special">(</span><span class="identifier">BOOST_VMD_TYPE_UDEF_SHAPES</span><span class="special">,</span><span class="identifier">UDEF_HEXAGON</span><span class="special">)</span>
</pre>
<h4>
<a name="variadic_macro_data.vmd_identifier_subtype.h4"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_identifier_subtype.subtype_register_the_v_type_name"></a></span><a class="link" href="vmd_identifier_subtype.html#variadic_macro_data.vmd_identifier_subtype.subtype_register_the_v_type_name">Subtype
register the v-type name for the subtype</a>
</h4>
<p>
Doing a subset register of the actual udef v-type is fairly easy once we understand
how to register an identifier subset. The only particular thing to realize
is that the type of any v-type is the v-type BOOST_VMD_TYPE_TYPE. So our subset
register of our new v-type BOOST_VMD_TYPE_UDEF_SHAPES is:
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SUBTYPE_REGISTER_BOOST_VMD_TYPE_UDEF_SHAPES</span> <span class="special">(</span><span class="identifier">BOOST_VMD_TYPE_TYPE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_UDEF_SHAPES</span><span class="special">)</span>
</pre>
<h4>
<a name="variadic_macro_data.vmd_identifier_subtype.h5"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_identifier_subtype.using_our_identifier_subset"></a></span><a class="link" href="vmd_identifier_subtype.html#variadic_macro_data.vmd_identifier_subtype.using_our_identifier_subset">Using
our identifier subset</a>
</h4>
<p>
Once we have added all of the above object-like macros for defining our user-defined
subtype to the udef_vmd_macros.hpp header file we have a new data type which
we can use generically just like we can use numbers or v-types generically.
It is important to include the header udef_vmd_macros.hpp in some translation
unit whenever we need the VMD functionality for our new data type. So in our
examples we will assume that an '#include udef_vmd_macros.hpp' precedes each
example.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">get_type</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE</span> <span class="identifier">UDEF_SQUARE</span>
<span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE2</span> <span class="number">217</span>
<span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE3</span> <span class="identifier">BOOST_VMD_TYPE_UDEF_SHAPES</span>
<span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE4</span> <span class="identifier">BOOST_VMD_TYPE_NUMBER</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">A_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'BOOST_VMD_TYPE_UDEF_SHAPES'</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">A_SEQUENCE2</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'BOOST_VMD_TYPE_NUMBER'</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">A_SEQUENCE3</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'BOOST_VMD_TYPE_TYPE'</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">A_SEQUENCE4</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'BOOST_VMD_TYPE_TYPE'</span>
</pre>
<p>
Here we see that when we use our BOOST_VMD_GET_TYPE macro on a single-element
sequence which is one of our user-defined subtype values we correctly get back
our user-defined subtype's v-type, just like we do when we ask for the type
of a number. Also when we use our BOOST_VMD_GET_TYPE macro on our user-defined
subtype's v-type itself we correctly get back the type of all v-types, which
is BOOST_VMD_TYPE_TYPE, just like we do when we ask for the type of the v-type
of a number.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">elem</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE5</span> <span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">)</span> <span class="identifier">UDEF_TRIANGLE</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">A_SEQUENCE5</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_UDEF_SHAPES,UDEF_TRIANGLE)'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">A_SEQUENCE5</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_TUPLE,(1,2))'</span>
</pre>
<p>
Here we see that we can use the return type modifier to get back both the type
and the value in a two-element tuple for our user-defined subtype just as we
so for any other type.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">equal</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE6</span> <span class="identifier">UDEF_CIRCLE</span>
<span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE7</span> <span class="number">168</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_SEQUENCE6</span><span class="special">,</span><span class="identifier">UDEF_CIRCLE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_UDEF_SHAPES</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'1'</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_SEQUENCE6</span><span class="special">,</span><span class="identifier">UDEF_CIRCLE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'0'</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_SEQUENCE7</span><span class="special">,</span><span class="number">168</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_NUMBER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'1'</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_SEQUENCE7</span><span class="special">,</span><span class="number">168</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_SEQ</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'0'</span>
</pre>
<p>
Here we can see that we can use the filter modifier with our user-defined subtype's
v-type just as we can do with any other v-type, such as the number v-type.
</p>
<p>
In all respects once we define our subtype and provide those definitions in
a header file, our user-defined subtype acts like any other v-type in our system.
Since VMD functionality is largely based on being able to recognize the type
of data in macro input being able to define another 'type', as an identifier
subtype, which VMD understands has value for the macro programmer.
</p>
<h4>
<a name="variadic_macro_data.vmd_identifier_subtype.h6"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_identifier_subtype.uniqueness_of_identifier_subtype"></a></span><a class="link" href="vmd_identifier_subtype.html#variadic_macro_data.vmd_identifier_subtype.uniqueness_of_identifier_subtype">Uniqueness
of identifier subtype values and v-type</a>
</h4>
<p>
When we define a new identifier subtype we need to be careful that the values
of that subtype and its actual v-type are unique identifiers within any translation
unit. This is the main difference between just defining identifiers and defining
an identifier subtype.
</p>
<p>
Recall that when we just register and pre-detect identifiers we will have no
problems if the same identifiers already have been registered and pre-detected
within the same translation unit. This is because we are just redefining the
exact same macro if this is the case.
</p>
<p>
But with identifier subtypes, when we use the BOOST_VMD_SUBTYPE_REGISTER_ macro
to associate our subtype's v-type with our subtype identifiers, we will have
problems if someone else has also defined an identifier subtype using the same
identifiers as we use since we will be redefining the same object-like macro
name with a different expansion. Even if someone else has registered/pre-detected
an identifier we are using for out subtype without defining a subtype based
on that identifier we will be causing a problem defining our subtype because
VMD macros which generically return the type of a sequence or sequence element
will return our subtype as the type rather than just BOOST_VMD_TYPE_IDENTIFIER
which some programmer might expect.
</p>
<p>
The gist of this is that if we define a user-defined subtype its identifiers
need to be unique within a given translation unit, and yet unique names make
it harder for an end-user to use macros more naturally. In our given example
with the mythical udef library we used identifiers such as 'UDEF_CIRCLE' etc.
instead of the more natural sounding CIRCLE. So with user-defined identifier
subtypes we have a tradeoff; we need unique identifier names both for our subtype
identifiers and the v-type for our subtype identifiers so as not to conflict
with others who might be using identifier subtypes, but those unique names
might make using macros less "natural" On the other hand, just registering/pre-detecting
identifiers has no such problem. This is an issue of which any user, looking
to create his own data type using VMD by defining user-defined subtypes, should
be aware.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_modifiers/vmd_modifiers_single.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_useful.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,64 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Controlling internal usage</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="prev" href="vmd_useful/vmd_empty_ppdata.html" title='Functionality for "empty" seqs and tuples'>
<link rel="next" href="vmd_reentrant.html" title="Boost PP re-entrant versions">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_useful/vmd_empty_ppdata.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_reentrant.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="variadic_macro_data.vmd_internal_macros"></a><a class="link" href="vmd_internal_macros.html" title="Controlling internal usage">Controlling internal
usage</a>
</h2></div></div></div>
<p>
VMD has a few object-like macros which the end-user of the library can use
to determine or change the way variadic macros are used in the library.
</p>
<p>
The macro BOOST_PP_VARIADICS is part of the Boost PP library, not part of VMD.
It is used to denote whether variadic data support exists for the particular
compiler the end-user is using. VMD also uses this macro to determine whether
variadic data support exists. An end-user of VMD can use this macro in his
own design to determine whether or not variadic macros are supported. Furthermore
an end-user of VMD can set this macro to 0 or non-zero, before including a
VMD header file, to force VMD to treat the particular compiler being used as
not supporting or supporting variadic macros. If a compiler does not support
variadic macro none of the macros in VMD are defined.
</p>
<p>
The macro BOOST_VMD_ASSERT_DATA controls whether or not an assert macro will
check its data. The default is that in compiler debug mode it will check the
data while in compiler release mode it will not check its data. The end-user
can change this by setting the macro to 0 to not check the data, or non-zero
to check the data, before including a VMD header file, or check the value if
necessary after including a VMD header file.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_useful/vmd_empty_ppdata.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_reentrant.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,645 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Macros with modifiers</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="prev" href="vmd_generic/vmd_assert.html" title="Testing for equality and inequality">
<link rel="next" href="vmd_modifiers/vmd_modifiers_filter.html" title="Filtering modifiers">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_generic/vmd_assert.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_modifiers/vmd_modifiers_filter.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="variadic_macro_data.vmd_modifiers"></a><a class="link" href="vmd_modifiers.html" title="Macros with modifiers">Macros with modifiers</a>
</h2></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="vmd_modifiers.html#variadic_macro_data.vmd_modifiers.vmd_modifiers_return_type">Return
type modifiers</a></span></dt>
<dt><span class="section"><a href="vmd_modifiers/vmd_modifiers_filter.html">Filtering
modifiers</a></span></dt>
<dt><span class="section"><a href="vmd_modifiers/vmd_modifiers_identifier.html">Identifier
modifiers</a></span></dt>
<dt><span class="section"><a href="vmd_modifiers/vmd_modifiers_splitting.html">Splitting
modifiers</a></span></dt>
<dt><span class="section"><a href="vmd_modifiers/vmd_modifiers_index.html">Index
modifiers</a></span></dt>
<dt><span class="section"><a href="vmd_modifiers/vmd_modifiers_single.html">Modifiers
and the single-element sequence</a></span></dt>
</dl></div>
<p>
The basic functionality for VMD macros parsing data types has been given using
the required parameters of those macros. This basic functionality may be perfectly
adequate for macro programmers to use VMD effectively in their programming
efforts.
</p>
<p>
A number of those macros take optional parameters, called in general "modifiers",
which enhance or change the functionality of those macros in various ways.
All modifiers are VMD identifiers.
</p>
<p>
In all situations modifiers are optional parameters which are parsed by VMD
to provide enhanced functionality for some of its macros. They are never required
as part of the basic functionality of a macro.
</p>
<p>
When modifiers are used as optional arguments to a macro they can be input
after the required parameters in any order and VMD will still handle the optional
parameters correctly.
</p>
<p>
There are two general types of modifiers, 'specific modifiers' and 'user-defined
modifiers'. Specific modifers start with BOOST_VMD_ and are both registered
and pre-detected identifiers known to VMD. The specific modifiers change the
expansion of particular macros in various ways which will be subsequently explained.
User-defined modifiers are user-defined identifiers which the end-user of specific
macros must register and pre-detect for himself. They also change the expansion
of particular macros in various ways which will be subsequently explained.
</p>
<p>
For any particular macro if a specific modifier is not appropriate it is just
ignored. This means that VMD never generates a preprocessing error or gives
an incorrect result just because a specific modifier does not apply for a particular
macro. Any modifier which is not recognized as a specific modifier is treated
as a user-defined modifier. In cases where a user-defined modifier is not appropriate
it is also just ignored.
</p>
<p>
The situations where modifiers can be used to enhance the basic functionality
of VMD macros can be divided by particular types of specific modifiers. Each
particular type of a specific modifier has a name given to it, functionality,
and set of identifiers associated with that particular type. Each particular
type of a specific modifier may be used as optional parameters in one or more
designated macros depending on the specific modifier type.
</p>
<p>
When more than one mutually exclusive specific modifier from a particular type
of modifier is specified as an optional parameter the last specified takes
effect. This allows the programmer to override a specific modifier by adding
the overridden identifier as an optional argument to the end of the macro's
invocation.
</p>
<p>
Header files for specific modifiers are automatically included when the header
files for macros taking those specific modifiers are included.
</p>
<p>
Header files for user-defined modifiers, which register and pre-detect those
user-defined modifiers, must be included as needed by the programmer using
those modifiers.
</p>
<p>
The following topics will explain each particular type of modifier and where
it may be used.
</p>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="variadic_macro_data.vmd_modifiers.vmd_modifiers_return_type"></a><a class="link" href="vmd_modifiers.html#variadic_macro_data.vmd_modifiers.vmd_modifiers_return_type" title="Return type modifiers">Return
type modifiers</a>
</h3></div></div></div>
<p>
A number of macros are capable of returning the type of data as a v-type
rather than, or along with, the data itself. The most obvious of these is
BOOST_VMD_GET_TYPE which generically returns the type of the input.
</p>
<p>
Return type modifiers turn on, turn off, or change the type of the data returned
in some way.
</p>
<p>
These modifiers are:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
BOOST_VMD_RETURN_NO_TYPE, do not return the type of data.
</li>
<li class="listitem">
BOOST_VMD_RETURN_TYPE, return the type of data parsing any tuple-like
syntactical construct as its most specific type. This means that any
tuple-like construct is parsed first as a possible list, next as a possible
array if it is not a list, and finally as a tuple if it is not a list
or an array.
</li>
<li class="listitem">
BOOST_VMD_RETURN_TYPE_LIST, parse any tuple-like syntactical construct
first as a possible list and only then as a tuple if it is not a list.
</li>
<li class="listitem">
BOOST_VMD_RETURN_TYPE_ARRAY, parse any tuple-like syntactical construct
first as a possible array and only then as a tuple if it is not an array.
</li>
<li class="listitem">
BOOST_VMD_RETURN_TYPE_TUPLE, parse any tuple-like syntactical construct
only as a tuple.
</li>
</ul></div>
<p>
When VMD parses input generically it must determine the type of each data
element of the input. For nearly all of the VMD data types this is never
a problem. For the array or list data types this can be a problem, as explained
when discussing parsing arrays and lists respectively using the specific
macros BOOST_VMD_IS_ARRAY and BOOST_VMD_IS_LIST. The problem is that a valid
tuple can be an invalid list or an invalid array, whose parsing as the more
specific type will lead to UB. Because of this when VMD parses input generically,
and only the data of an element is needed to continue parsing correctly,
it parses all tuple-like data as a tuple and never as a list or an array.
</p>
<p>
When VMD parses input generically, and the type of the data is required in
some way as part of the return of a macro, VMD by default parses for the
most specific type of each data element in order to return the most accurate
type. In this situation by default the BOOST_VMD_RETURN_TYPE modifier is
internally in effect without having to be specified.
</p>
<p>
If more than one of the return type modifiers are specified as optional parameters
the last one specified is in effect.
</p>
<h5>
<a name="variadic_macro_data.vmd_modifiers.vmd_modifiers_return_type.h0"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_modifiers.vmd_modifiers_return_type.usage_with_boost_vmd_get_type"></a></span><a class="link" href="vmd_modifiers.html#variadic_macro_data.vmd_modifiers.vmd_modifiers_return_type.usage_with_boost_vmd_get_type">Usage
with BOOST_VMD_GET_TYPE</a>
</h5>
<p>
The only macro in which VMD without the use of modifiers is being asked to
return the type of data is BOOST_VMD_GET_TYPE. For this macro the BOOST_VMD_RETURN_TYPE
modifier is internally in effect so if no return type modifiers are input
as optional parameters BOOST_VMD_GET_TYPE looks for the most specific type.
</p>
<p>
For the BOOST_VMD_GET_TYPE macro the optional return type modifier BOOST_VMD_RETURN_NO_TYPE,
if specified, is always ignored since the purpose of BOOST_VMD_GET_TYPE is
solely to return the v-type.
</p>
<p>
Let's look at how this works with BOOST_VMD_GET_TYPE by specifying VMD sequences
that have tuples which may or may not be valid lists or arrays.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">get_type</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE_IS_ARRAY</span> <span class="special">(</span><span class="number">2</span><span class="special">,(</span><span class="number">3</span><span class="special">,</span><span class="number">4</span><span class="special">))</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE_IS_LIST</span> <span class="special">(</span><span class="identifier">anydata</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE_IS_LIST_OR_ARRAY</span> <span class="special">(</span><span class="number">2</span><span class="special">,(</span><span class="number">3</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">))</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE_BUT_INVALID_ARRAY</span> <span class="special">(&amp;</span><span class="number">2</span><span class="special">,(</span><span class="number">3</span><span class="special">,</span><span class="number">4</span><span class="special">))</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE_BUT_INVALID_LIST</span> <span class="special">(</span><span class="identifier">anydata</span><span class="special">,^</span><span class="identifier">BOOST_PP_NIL</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_EMPTY</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_MULTI</span> <span class="identifier">TUPLE_BUT_INVALID_ARRAY</span> <span class="identifier">TUPLE_BUT_INVALID_LIST</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">TUPLE_IS_ARRAY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_ARRAY</span><span class="special">,</span> <span class="identifier">the</span> <span class="identifier">most</span> <span class="identifier">specific</span> <span class="identifier">type</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">TUPLE_IS_ARRAY</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_TUPLE</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">TUPLE_IS_ARRAY</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_ARRAY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_ARRAY</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">TUPLE_IS_ARRAY</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_TUPLE</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">TUPLE_IS_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_LIST</span><span class="special">,</span> <span class="identifier">the</span> <span class="identifier">most</span> <span class="identifier">specific</span> <span class="identifier">type</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">TUPLE_IS_LIST</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_TUPLE</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">TUPLE_IS_LIST</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_ARRAY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_TUPLE</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">TUPLE_IS_LIST</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_LIST</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">TUPLE_IS_LIST_OR_ARRAY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_LIST</span><span class="special">,</span> <span class="identifier">the</span> <span class="identifier">most</span> <span class="identifier">specific</span> <span class="identifier">type</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">TUPLE_IS_LIST_OR_ARRAY</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_TUPLE</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">TUPLE_IS_LIST_OR_ARRAY</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_ARRAY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_ARRAY</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">TUPLE_IS_LIST_OR_ARRAY</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_LIST</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">TUPLE_BUT_INVALID_ARRAY</span><span class="special">)</span> <span class="identifier">will</span> <span class="identifier">give</span> <span class="identifier">UB</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">TUPLE_BUT_INVALID_ARRAY</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_TUPLE</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">TUPLE_BUT_INVALID_ARRAY</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_ARRAY</span><span class="special">)</span> <span class="identifier">will</span> <span class="identifier">give</span> <span class="identifier">UB</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">TUPLE_BUT_INVALID_ARRAY</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_TUPLE</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">TUPLE_BUT_INVALID_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="identifier">give</span> <span class="identifier">UB</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">TUPLE_BUT_INVALID_LIST</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_TUPLE</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">TUPLE_BUT_INVALID_LIST</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_ARRAY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_TUPLE</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">TUPLE_BUT_INVALID_LIST</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="identifier">give</span> <span class="identifier">UB</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">SEQUENCE_EMPTY</span><span class="special">)</span>
<span class="identifier">will</span> <span class="identifier">always</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_EMPTY</span> <span class="identifier">even</span> <span class="keyword">if</span> <span class="identifier">we</span> <span class="identifier">add</span> <span class="identifier">any</span> <span class="keyword">return</span> <span class="identifier">type</span> <span class="identifier">modifiers</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">SEQUENCE_MULTI</span><span class="special">)</span>
<span class="identifier">will</span> <span class="identifier">always</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_SEQUENCE</span> <span class="identifier">even</span> <span class="keyword">if</span> <span class="identifier">we</span> <span class="identifier">add</span> <span class="identifier">any</span> <span class="keyword">return</span> <span class="identifier">type</span> <span class="identifier">modifiers</span>
</pre>
<h5>
<a name="variadic_macro_data.vmd_modifiers.vmd_modifiers_return_type.h1"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_modifiers.vmd_modifiers_return_type.usage_with_sequence_converting_m"></a></span><a class="link" href="vmd_modifiers.html#variadic_macro_data.vmd_modifiers.vmd_modifiers_return_type.usage_with_sequence_converting_m">Usage
with sequence converting macros</a>
</h5>
<p>
The sequence converting macros converts a sequence to a composite Boost PP
data type or to variadic data, where each element's data in the sequence
becomes an element in the destination composite type. The macros are:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
BOOST_VMD_TO_ARRAY, converts the sequence to an array
</li>
<li class="listitem">
BOOST_VMD_TO_LIST, converts the sequence to a list
</li>
<li class="listitem">
BOOST_VMD_TO_SEQ, converts the sequence to a seq
</li>
<li class="listitem">
BOOST_VMD_TO_TUPLE, converts the sequence to a tuple
</li>
<li class="listitem">
BOOST_VMD_ENUM, converts the sequence to variadic data
</li>
</ul></div>
<p>
When it does the conversion, using just the required parameter of the sequence
itself, it converts only the data value of each sequence element to the elements
of a composite Boost PP data type or variadic data. Because it needs only
the data value of each sequence element it determines the type of each sequence
element as the most general type that it can be. This means that all tuple-like
data are parsed as tuples rather than as possible lists or arrays.
</p>
<p>
Using a return type modifier we can convert from a VMD sequence to a Boost
PP composite data type or variadic data and retain the type of data of each
element in the sequence as part of the conversion. When doing this each of
the converted elements of the composite data type becomes a two-element tuple
where the first element is the type of the data and the second element is
the data itself.
</p>
<p>
For the sequence conversion macros the default return type modifier internally
set is BOOST_VMD_RETURN_NO_TYPE, which means that the type is not retained.
By specifying another optional return type modifier we tell the conversion
to preserve the type in the conversion output.
</p>
<p>
If the sequence is empty, since there are no sequence elements, any return
type modifier we use accomplishes nothing but is fine to use.
</p>
<p>
First we show how sequence conversion macros work with the BOOST_VMD_RETURN_TYPE
modifier, which always parses for the most specific type.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="keyword">enum</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">to_array</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">to_list</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">to_seq</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">to_tuple</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_ANID</span> <span class="special">(</span><span class="identifier">ANID</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_EMPTY_1</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_SINGLE</span> <span class="number">35</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_SINGLE_ID</span> <span class="identifier">ANID</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_SINGLE_ARRAY</span> <span class="special">(</span><span class="number">3</span><span class="special">,(</span><span class="number">0</span><span class="special">,</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">))</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_SINGLE_LIST</span> <span class="special">(</span><span class="identifier">data</span><span class="special">,(</span><span class="identifier">more_data</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">))</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_MULTI_1</span> <span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="number">1</span><span class="special">)</span> <span class="special">(</span><span class="number">2</span><span class="special">)(</span><span class="number">3</span><span class="special">)(</span><span class="number">4</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_MULTI_2</span> <span class="identifier">BOOST_VMD_TYPE_SEQ</span> <span class="special">(</span><span class="number">2</span><span class="special">,(</span><span class="number">5</span><span class="special">,</span><span class="number">6</span><span class="special">))</span>
<span class="identifier">BOOST_VMD_TO_ARRAY</span><span class="special">(</span><span class="identifier">SEQUENCE_EMPTY_1</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">an</span> <span class="identifier">empty</span> <span class="identifier">array</span> <span class="char">'(0,())'</span>
<span class="identifier">BOOST_VMD_TO_ARRAY</span><span class="special">(</span><span class="identifier">SEQUENCE_EMPTY_1</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">an</span> <span class="identifier">empty</span> <span class="identifier">array</span> <span class="char">'(0,())'</span>
<span class="identifier">BOOST_VMD_TO_LIST</span><span class="special">(</span><span class="identifier">SEQUENCE_SINGLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">a</span> <span class="identifier">one</span><span class="special">-</span><span class="identifier">element</span> <span class="identifier">list</span> <span class="char">'(35,BOOST_PP_NIL)'</span>
<span class="identifier">BOOST_VMD_TO_LIST</span><span class="special">(</span><span class="identifier">SEQUENCE_SINGLE</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span>
<span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">a</span> <span class="identifier">one</span><span class="special">-</span><span class="identifier">element</span> <span class="identifier">list</span> <span class="char">'((BOOST_VMD_TYPE_NUMBER,35),BOOST_PP_NIL)'</span>
<span class="identifier">BOOST_VMD_TO_SEQ</span><span class="special">(</span><span class="identifier">SEQUENCE_SINGLE_ID</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">a</span> <span class="identifier">one</span><span class="special">-</span><span class="identifier">element</span> <span class="identifier">seq</span> <span class="char">'(ANID)'</span>
<span class="identifier">BOOST_VMD_TO_SEQ</span><span class="special">(</span><span class="identifier">SEQUENCE_SINGLE_ID</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span>
<span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">a</span> <span class="identifier">one</span><span class="special">-</span><span class="identifier">element</span> <span class="identifier">seq</span> <span class="char">'((BOOST_VMD_TYPE_IDENTIFIER,ANID))'</span>
<span class="identifier">BOOST_VMD_TO_TUPLE</span><span class="special">(</span><span class="identifier">SEQUENCE_SINGLE_ARRAY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">a</span> <span class="identifier">single</span> <span class="identifier">element</span> <span class="identifier">tuple</span> <span class="char">'((3,(0,1,2)))'</span>
<span class="identifier">BOOST_VMD_TO_TUPLE</span><span class="special">(</span><span class="identifier">SEQUENCE_SINGLE_ARRAY</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span>
<span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">a</span> <span class="identifier">single</span> <span class="identifier">element</span> <span class="identifier">tuple</span> <span class="char">'((BOOST_VMD_TYPE_ARRAY,(3,(0,1,2))))'</span>
<span class="identifier">BOOST_VMD_ENUM</span><span class="special">(</span><span class="identifier">SEQUENCE_SINGLE_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">the</span> <span class="identifier">single</span><span class="special">-</span><span class="identifier">element</span> <span class="char">'(data,(more_data,BOOST_PP_NIL))'</span>
<span class="identifier">BOOST_VMD_ENUM</span><span class="special">(</span><span class="identifier">SEQUENCE_SINGLE_LIST</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span>
<span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">the</span> <span class="identifier">single</span> <span class="identifier">element</span> <span class="char">'(BOOST_VMD_TYPE_LIST,(data,(more_data,BOOST_PP_NIL)))'</span>
<span class="identifier">BOOST_VMD_TO_TUPLE</span><span class="special">(</span><span class="identifier">SEQUENCE_MULTI_1</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">a</span> <span class="identifier">multi</span><span class="special">-</span><span class="identifier">element</span> <span class="identifier">tuple</span> <span class="char">'((0,1),(2)(3)(4))'</span>
<span class="identifier">BOOST_VMD_TO_TUPLE</span><span class="special">(</span><span class="identifier">SEQUENCE_MULTI_1</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span>
<span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">a</span> <span class="identifier">multi</span><span class="special">-</span><span class="identifier">element</span> <span class="identifier">tuple</span> <span class="char">'((BOOST_VMD_TYPE_TUPLE,(0,1)),(BOOST_VMD_TYPE_SEQ,(2)(3)(4)))'</span>
<span class="identifier">BOOST_VMD_ENUM</span><span class="special">(</span><span class="identifier">SEQUENCE_MULTI_2</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">multi</span><span class="special">-</span><span class="identifier">element</span> <span class="identifier">variadic</span> <span class="identifier">data</span> <span class="char">'BOOST_VMD_TYPE_SEQ,(2,(5,6))'</span>
<span class="identifier">BOOST_VMD_ENUM</span><span class="special">(</span><span class="identifier">SEQUENCE_MULTI_2</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span>
<span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">multi</span><span class="special">-</span><span class="identifier">element</span> <span class="identifier">variadic</span> <span class="identifier">data</span> <span class="char">'(BOOST_VMD_TYPE_TYPE,BOOST_VMD_TYPE_SEQ),(BOOST_VMD_TYPE_ARRAY,(2,(5,6)))'</span>
</pre>
<p>
Lets look at how we might use other return type modifiers when doing conversions
to avoid UB if we want the type as part of the conversion but the type might
be a valid tuple while being an invalid list or array.
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">TUPLE_IS_VALID_ARRAY</span> <span class="special">(</span><span class="number">2</span><span class="special">,(</span><span class="number">3</span><span class="special">,</span><span class="number">4</span><span class="special">))</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE_IS_VALID_LIST</span> <span class="special">(</span><span class="identifier">anydata</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE_BUT_INVALID_ARRAY_2</span> <span class="special">(&amp;</span><span class="number">2</span><span class="special">,(</span><span class="number">3</span><span class="special">,</span><span class="number">4</span><span class="special">))</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE_BUT_INVALID_LIST_2</span> <span class="special">(</span><span class="identifier">anydata</span><span class="special">,^</span><span class="identifier">BOOST_PP_NIL</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_MULTI_T1</span> <span class="identifier">TUPLE_IS_VALID_ARRAY</span> <span class="identifier">TUPLE_IS_VALID_LIST</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_MULTI_T2</span> <span class="identifier">TUPLE_BUT_INVALID_ARRAY_2</span> <span class="identifier">TUPLE_IS_VALID_LIST</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_MULTI_T3</span> <span class="identifier">TUPLE_IS_VALID_ARRAY</span> <span class="identifier">TUPLE_BUT_INVALID_LIST_2</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_MULTI_T4</span> <span class="identifier">TUPLE_BUT_INVALID_ARRAY_2</span> <span class="identifier">TUPLE_BUT_INVALID_LIST_2</span>
</pre>
<p>
We present a number of uses of various sequence conversions with each of
our four different sequences, and show their results.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">to_seq</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_VMD_TO_SEQ</span><span class="special">(</span><span class="identifier">SEQUENCE_MULTI_T1</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span>
<span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">the</span> <span class="identifier">seq</span> <span class="char">'((BOOST_VMD_TYPE_ARRAY,(2,(3,4)))) ((BOOST_VMD_TYPE_LIST,(anydata,BOOST_PP_NIL)))'</span>
<span class="identifier">BOOST_VMD_TO_SEQ</span><span class="special">(</span><span class="identifier">SEQUENCE_MULTI_T1</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_ARRAY</span><span class="special">)</span>
<span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">the</span> <span class="identifier">seq</span> <span class="char">'((BOOST_VMD_TYPE_ARRAY,(2,(3,4)))) ((BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL)))'</span>
<span class="identifier">BOOST_VMD_TO_SEQ</span><span class="special">(</span><span class="identifier">SEQUENCE_MULTI_T1</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_LIST</span><span class="special">)</span>
<span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">the</span> <span class="identifier">seq</span> <span class="char">'((BOOST_VMD_TYPE_TUPLE,(2,(3,4)))) ((BOOST_VMD_TYPE_LIST,(anydata,BOOST_PP_NIL)))'</span>
<span class="identifier">BOOST_VMD_TO_SEQ</span><span class="special">(</span><span class="identifier">SEQUENCE_MULTI_T1</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_TUPLE</span><span class="special">)</span>
<span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">the</span> <span class="identifier">seq</span> <span class="char">'((BOOST_VMD_TYPE_TUPLE,(2,(3,4)))) ((BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL)))'</span>
</pre>
<p>
The SEQUENCE_MULTI_T1 is a valid array followed by a valid list. All return
type modifiers produce their results without any UBs.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">to_tuple</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_VMD_TO_TUPLE</span><span class="special">(</span><span class="identifier">SEQUENCE_MULTI_T2</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span>
<span class="identifier">will</span> <span class="identifier">produce</span> <span class="identifier">UB</span> <span class="identifier">when</span> <span class="identifier">attempting</span> <span class="identifier">to</span> <span class="identifier">parse</span> <span class="identifier">the</span> <span class="identifier">invalid</span> <span class="identifier">array</span> <span class="identifier">as</span> <span class="identifier">an</span> <span class="identifier">array</span>
<span class="identifier">BOOST_VMD_TO_TUPLE</span><span class="special">(</span><span class="identifier">SEQUENCE_MULTI_T2</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_ARRAY</span><span class="special">)</span>
<span class="identifier">will</span> <span class="identifier">produce</span> <span class="identifier">UB</span> <span class="identifier">when</span> <span class="identifier">attempting</span> <span class="identifier">to</span> <span class="identifier">parse</span> <span class="identifier">the</span> <span class="identifier">invalid</span> <span class="identifier">array</span> <span class="identifier">as</span> <span class="identifier">an</span> <span class="identifier">array</span>
<span class="identifier">BOOST_VMD_TO_TUPLE</span><span class="special">(</span><span class="identifier">SEQUENCE_MULTI_T2</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_LIST</span><span class="special">)</span>
<span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">the</span> <span class="identifier">tuple</span> <span class="char">'((BOOST_VMD_TYPE_TUPLE,(&amp;2,(3,4))),(BOOST_VMD_TYPE_LIST,(anydata,BOOST_PP_NIL)))'</span>
<span class="identifier">BOOST_VMD_TO_TUPLE</span><span class="special">(</span><span class="identifier">SEQUENCE_MULTI_T2</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_TUPLE</span><span class="special">)</span>
<span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">the</span> <span class="identifier">tuple</span> <span class="char">'((BOOST_VMD_TYPE_TUPLE,(&amp;2,(3,4))),(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL)))'</span>
</pre>
<p>
The SEQUENCE_MULTI_T2 is an invalid array, but valid tuple, followed by a
valid list.
</p>
<p>
In sequence conversion we will get UB whenever we use a return type modifier
that parses the data type of the invalid array as an array. But if we use
the return type modifiers BOOST_VMD_RETURN_TYPE_LIST or BOOST_VMD_RETURN_TYPE_TUPLE
we are never parsing the invalid array as an array but as a tuple instead
and therefore we successfully return the type of the invalid array as a BOOST_VMD_TYPE_TUPLE.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">to_array</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_VMD_TO_ARRAY</span><span class="special">(</span><span class="identifier">SEQUENCE_MULTI_T3</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span>
<span class="identifier">will</span> <span class="identifier">produce</span> <span class="identifier">UB</span> <span class="identifier">when</span> <span class="identifier">attempting</span> <span class="identifier">to</span> <span class="identifier">parse</span> <span class="identifier">the</span> <span class="identifier">invalid</span> <span class="identifier">list</span> <span class="identifier">as</span> <span class="identifier">a</span> <span class="identifier">list</span>
<span class="identifier">BOOST_VMD_TO_ARRAY</span><span class="special">(</span><span class="identifier">SEQUENCE_MULTI_T3</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_LIST</span><span class="special">)</span>
<span class="identifier">will</span> <span class="identifier">produce</span> <span class="identifier">UB</span> <span class="identifier">when</span> <span class="identifier">attempting</span> <span class="identifier">to</span> <span class="identifier">parse</span> <span class="identifier">the</span> <span class="identifier">invalid</span> <span class="identifier">list</span> <span class="identifier">as</span> <span class="identifier">a</span> <span class="identifier">list</span>
<span class="identifier">BOOST_VMD_TO_ARRAY</span><span class="special">(</span><span class="identifier">SEQUENCE_MULTI_T3</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_ARRAY</span><span class="special">)</span>
<span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">the</span> <span class="identifier">array</span> <span class="char">'(2,((BOOST_VMD_TYPE_ARRAY,(2,(3,4))),(BOOST_VMD_TYPE_TUPLE,(anydata,^BOOST_PP_NIL))))'</span>
<span class="identifier">BOOST_VMD_TO_ARRAY</span><span class="special">(</span><span class="identifier">SEQUENCE_MULTI_T3</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_TUPLE</span><span class="special">)</span>
<span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">the</span> <span class="identifier">array</span> <span class="char">'(2,((BOOST_VMD_TYPE_TUPLE,(2,(3,4))),(BOOST_VMD_TYPE_TUPLE,(anydata,^BOOST_PP_NIL))))'</span>
</pre>
<p>
The SEQUENCE_MULTI_T3 is a valid array followed by an invalid list, but a
valid tuple.
</p>
<p>
In sequence conversion we will get UBs whenever we use a return type modifier
that parses the data type of the invalid list as a list. But if we use the
return type modifiers BOOST_VMD_RETURN_TYPE_ARRAY or BOOST_VMD_RETURN_TYPE_TUPLE
we are never parsing the invalid list as a list but as a tuple instead and
therefore we successfully return the type of the invalid list as a BOOST_VMD_TYPE_TUPLE.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">to_list</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_VMD_TO_LIST</span><span class="special">(</span><span class="identifier">SEQUENCE_MULTI_T4</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span>
<span class="identifier">will</span> <span class="identifier">produce</span> <span class="identifier">UB</span> <span class="identifier">when</span> <span class="identifier">attempting</span> <span class="identifier">to</span> <span class="identifier">parse</span> <span class="identifier">the</span> <span class="identifier">invalid</span> <span class="identifier">array</span> <span class="keyword">or</span> <span class="identifier">invalid</span> <span class="identifier">list</span>
<span class="identifier">BOOST_VMD_TO_LIST</span><span class="special">(</span><span class="identifier">SEQUENCE_MULTI_T4</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_ARRAY</span><span class="special">)</span>
<span class="identifier">will</span> <span class="identifier">produce</span> <span class="identifier">UB</span> <span class="identifier">when</span> <span class="identifier">attempting</span> <span class="identifier">to</span> <span class="identifier">parse</span> <span class="identifier">the</span> <span class="identifier">invalid</span> <span class="identifier">array</span>
<span class="identifier">BOOST_VMD_TO_LIST</span><span class="special">(</span><span class="identifier">SEQUENCE_MULTI_T4</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_LIST</span><span class="special">)</span>
<span class="identifier">will</span> <span class="identifier">produce</span> <span class="identifier">UB</span> <span class="identifier">when</span> <span class="identifier">attempting</span> <span class="identifier">to</span> <span class="identifier">parse</span> <span class="identifier">the</span> <span class="identifier">invalid</span> <span class="identifier">list</span>
<span class="identifier">BOOST_VMD_TO_LIST</span><span class="special">(</span><span class="identifier">SEQUENCE_MULTI_T4</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_TUPLE</span><span class="special">)</span>
<span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">the</span> <span class="identifier">list</span> <span class="char">'((BOOST_VMD_TYPE_TUPLE,(&amp;2,(3,4))),((BOOST_VMD_TYPE_TUPLE,(anydata,^BOOST_PP_NIL)),BOOST_PP_NIL))'</span>
</pre>
<p>
The SEQUENCE_MULTI_T4 is an invalid array, but valid tuple, followed by an
invalid list, but valid tuple.
</p>
<p>
In sequence conversion we will get UBs whenever we use a return type modifier
that parses the sequence other than looking for only valid tuples. So here
we must use the return type modifier BOOST_VMD_RETURN_TYPE_TUPLE for a sequence
conversion without generating UBs.
</p>
<h5>
<a name="variadic_macro_data.vmd_modifiers.vmd_modifiers_return_type.h2"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_modifiers.vmd_modifiers_return_type.usage_with_boost_vmd_elem"></a></span><a class="link" href="vmd_modifiers.html#variadic_macro_data.vmd_modifiers.vmd_modifiers_return_type.usage_with_boost_vmd_elem">Usage
with BOOST_VMD_ELEM</a>
</h5>
<p>
The default functionality of BOOST_VMD_ELEM when the required parameters
are used is to return the particular element's data. When BOOST_VMD_ELEM
does this it parses all elements of the sequence by determining the most
general type of data for each element. The parsing algorithm stops when it
reaches the element number whose data is returned. This means that all tuple-like
data are parsed as tuples rather than as possible lists or arrays.
</p>
<p>
Using return type modifiers as optional parameters we can tell BOOST_VMD_ELEM
to return the type of the element found, as well as its data, in the form
of a two element tuple. The first element of the tuple is the type of the
data and the second element of the tuple is the data itself.
</p>
<p>
When we use a return type modifier with BOOST_VMD_ELEM, which tells us to
return the type of the data along with the data, the particular modifier
only tells BOOST_VMD_ELEM how to parse the type of data for the element found.
BOOST_VMD_ELEM will continue to parse elements in the sequence preceding
the element found by determining the most general type of the data since
this is the safest way of parsing the data itself.
</p>
<p>
Using the return type modifier BOOST_VMD_RETURN_TYPE with BOOST_VMD_ELEM
is perfectly safe as long as the particular element found is not an invalid
list or array, but a valid tuple. It is when the element found may be an
invalid list or invalid array that we must use other return type modifiers
in order to parse the type of the element correctly.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">elem</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_ANID_E</span> <span class="special">(</span><span class="identifier">ANID_E</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_SINGLE_E</span> <span class="number">35</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_SINGLE_E2</span> <span class="identifier">ANID_E</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_MULTI_E</span> <span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="number">1</span><span class="special">)</span> <span class="special">(</span><span class="number">2</span><span class="special">)(</span><span class="number">3</span><span class="special">)(</span><span class="number">4</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_MULTI_E_2</span> <span class="identifier">BOOST_VMD_TYPE_SEQ</span> <span class="special">(</span><span class="number">2</span><span class="special">,(</span><span class="number">5</span><span class="special">,</span><span class="number">6</span><span class="special">))</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">SEQUENCE_SINGLE_E</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'35'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">SEQUENCE_SINGLE_E</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_NUMBER,35)'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">SEQUENCE_SINGLE_E2</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'ANID_E'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">SEQUENCE_SINGLE_E2</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_IDENTIFIER,ANID_E)'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(2)(3)(4)'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_SEQ,(2)(3)(4))'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E_2</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'BOOST_VMD_TYPE_SEQ'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E_2</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_TYPE,BOOST_VMD_TYPE_SEQ)'</span>
</pre>
<p>
When we use the other return type modifiers with BOOST_VMD_ELEM we do so
because the element we want may be an invalid list or an invalid array but
a valid tuple and yet we still want its type returned as part of the result.
</p>
<p>
Let's look at how this works with BOOST_VMD_ELEM by specifying VMD sequences
that have tuples which are in the form of arrays or lists which cannot be
parsed as such by VMD without generating UBs.
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">TUPLE_IS_VALID_ARRAY_E</span> <span class="special">(</span><span class="number">2</span><span class="special">,(</span><span class="number">3</span><span class="special">,</span><span class="number">4</span><span class="special">))</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE_IS_VALID_LIST_E</span> <span class="special">(</span><span class="identifier">anydata</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE_BUT_INVALID_ARRAY_E</span> <span class="special">(&amp;</span><span class="number">2</span><span class="special">,(</span><span class="number">3</span><span class="special">,</span><span class="number">4</span><span class="special">))</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE_BUT_INVALID_LIST_E</span> <span class="special">(</span><span class="identifier">anydata</span><span class="special">,^</span><span class="identifier">BOOST_PP_NIL</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_MULTI_E1</span> <span class="identifier">TUPLE_IS_VALID_ARRAY_E</span> <span class="identifier">TUPLE_IS_VALID_LIST_E</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_MULTI_E2</span> <span class="identifier">TUPLE_BUT_INVALID_ARRAY_E</span> <span class="identifier">TUPLE_IS_VALID_LIST_E</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_MULTI_E3</span> <span class="identifier">TUPLE_IS_VALID_ARRAY_E</span> <span class="identifier">TUPLE_BUT_INVALID_LIST_E</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQUENCE_MULTI_E4</span> <span class="identifier">TUPLE_BUT_INVALID_ARRAY_E</span> <span class="identifier">TUPLE_BUT_INVALID_LIST_E</span>
</pre>
<p>
We present a number of uses of BOOST_VMD_ELEM with each of our four different
sequences, and show their results.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">elem</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E1</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_ARRAY,(2,(3,4)))'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E1</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_ARRAY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_ARRAY,(2,(3,4)))'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E1</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_TUPLE,(2,(3,4)))'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E1</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_TUPLE,(2,(3,4)))'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E1</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_LIST,(anydata,BOOST_PP_NIL))'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E1</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_ARRAY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL))'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E1</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_LIST,(anydata,BOOST_PP_NIL))'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E1</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL))'</span>
</pre>
<p>
The SEQUENCE_MULTI_E1 is a valid array followed by a valid list. All return
type modifiers produce their results without any UBs.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">elem</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E2</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span>
<span class="identifier">will</span> <span class="identifier">produce</span> <span class="identifier">UB</span> <span class="identifier">when</span> <span class="identifier">attempting</span> <span class="identifier">to</span> <span class="identifier">parse</span> <span class="identifier">the</span> <span class="identifier">invalid</span> <span class="identifier">array</span> <span class="identifier">as</span> <span class="identifier">an</span> <span class="identifier">array</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E2</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_ARRAY</span><span class="special">)</span>
<span class="identifier">will</span> <span class="identifier">produce</span> <span class="identifier">UB</span> <span class="identifier">when</span> <span class="identifier">attempting</span> <span class="identifier">to</span> <span class="identifier">parse</span> <span class="identifier">the</span> <span class="identifier">invalid</span> <span class="identifier">array</span> <span class="identifier">as</span> <span class="identifier">an</span> <span class="identifier">array</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E2</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_TUPLE,(&amp;2,(3,4)))'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E2</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_TUPLE,(&amp;2,(3,4)))'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E2</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_LIST,(anydata,BOOST_PP_NIL))'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E2</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_ARRAY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL))'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E2</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_LIST,(anydata,BOOST_PP_NIL))'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E2</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL))'</span>
</pre>
<p>
The SEQUENCE_MULTI_E2 is an invalid array, but valid tuple, followed by a
valid list.
</p>
<p>
When we access element 0 of our sequence, and use a return type modifier
that parses its data type as an array we will get UB. But if we use the return
type modifiers BOOST_VMD_RETURN_TYPE_LIST or BOOST_VMD_RETURN_TYPE_TUPLE
we are never parsing the invalid array as an array but as a tuple instead
and therefore we successfully return the type of the invalid array as a BOOST_VMD_TYPE_TUPLE.
</p>
<p>
When we access element 1 of our sequence, which is both a valid list and
a valid tuple, we will never get UB. We will get the return type of the element
based on which return type modifier we use.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">elem</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E3</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_ARRAY,(2,(3,4)))'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E3</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_ARRAY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_ARRAY,(2,(3,4)))'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E3</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_TUPLE,(2,(3,4)))'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E3</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_TUPLE,(2,(3,4)))'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E3</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span>
<span class="identifier">will</span> <span class="identifier">produce</span> <span class="identifier">UB</span> <span class="identifier">when</span> <span class="identifier">attempting</span> <span class="identifier">to</span> <span class="identifier">parse</span> <span class="identifier">the</span> <span class="identifier">invalid</span> <span class="identifier">list</span> <span class="identifier">as</span> <span class="identifier">a</span> <span class="identifier">list</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E3</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_ARRAY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL))'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E3</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_LIST</span><span class="special">)</span>
<span class="identifier">will</span> <span class="identifier">produce</span> <span class="identifier">UB</span> <span class="identifier">when</span> <span class="identifier">attempting</span> <span class="identifier">to</span> <span class="identifier">parse</span> <span class="identifier">the</span> <span class="identifier">invalid</span> <span class="identifier">list</span> <span class="identifier">as</span> <span class="identifier">a</span> <span class="identifier">list</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E3</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL))'</span>
</pre>
<p>
The SEQUENCE_MULTI_E3 is a valid array followed by an invalid list, but valid
tuple.
</p>
<p>
When we access element 0 of our sequence, which is both a valid array and
a valid tuple, we will never get UB. We will get the return type of the element
based on which return type modifier we use.
</p>
<p>
When we access element 1 of our sequence, and use a return type modifier
that parses its data type as a list we will get UB. But if we use the return
type modifiers BOOST_VMD_RETURN_TYPE_ARRAY or BOOST_VMD_RETURN_TYPE_TUPLE
we are never parsing the invalid list as a list but as a tuple instead and
therefore we successfully return the type of the invalid list as a BOOST_VMD_TYPE_TUPLE.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">elem</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E4</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span>
<span class="identifier">will</span> <span class="identifier">produce</span> <span class="identifier">UB</span> <span class="identifier">when</span> <span class="identifier">attempting</span> <span class="identifier">to</span> <span class="identifier">parse</span> <span class="identifier">the</span> <span class="identifier">invalid</span> <span class="identifier">array</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E4</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_ARRAY</span><span class="special">)</span>
<span class="identifier">will</span> <span class="identifier">produce</span> <span class="identifier">UB</span> <span class="identifier">when</span> <span class="identifier">attempting</span> <span class="identifier">to</span> <span class="identifier">parse</span> <span class="identifier">the</span> <span class="identifier">invalid</span> <span class="identifier">array</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E4</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_TUPLE,(2,(3,4)))'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E4</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_TUPLE,(2,(3,4)))'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E4</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span>
<span class="identifier">will</span> <span class="identifier">produce</span> <span class="identifier">UB</span> <span class="identifier">when</span> <span class="identifier">attempting</span> <span class="identifier">to</span> <span class="identifier">parse</span> <span class="identifier">the</span> <span class="identifier">invalid</span> <span class="identifier">list</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E4</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_ARRAY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL))'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E4</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_LIST</span><span class="special">)</span>
<span class="identifier">will</span> <span class="identifier">produce</span> <span class="identifier">UB</span> <span class="identifier">when</span> <span class="identifier">attempting</span> <span class="identifier">to</span> <span class="identifier">parse</span> <span class="identifier">the</span> <span class="identifier">invalid</span> <span class="identifier">list</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">SEQUENCE_MULTI_E4</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL))'</span>
</pre>
<p>
The SEQUENCE_MULTI_E4 is an invalid array, but valid tuple, followed by an
invalid list, but valid tuple.
</p>
<p>
When we access element 0 of our sequence, which is an invalid array but a
valid tuple, we must use a return type modifier which does not parse element
0 as an array, else we will get UB. This means we must use the return type
modifiers BOOST_VMD_RETURN_TYPE_LIST or BOOST_VMD_RETURN_TYPE_TUPLE so we
are never parsing the invalid array as an array but as a tuple instead and
therefore we successfully return the type of the invalid array as a BOOST_VMD_TYPE_TUPLE.
</p>
<p>
When we access element 1 of our sequence, which is an invalid list but a
valid tuple, we must use a return type modifier which does not parse element
1 as a list, else we will get UB. This means we must use the return type
modifiers BOOST_VMD_RETURN_TYPE_ARRAY or BOOST_VMD_RETURN_TYPE_TUPLE so we
are never parsing the invalid list as a list but as a tuple instead and therefore
we successfully return the type of the invalid list as a BOOST_VMD_TYPE_TUPLE.
</p>
<h5>
<a name="variadic_macro_data.vmd_modifiers.vmd_modifiers_return_type.h3"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_modifiers.vmd_modifiers_return_type.usage_with_other_modifiers_of_bo"></a></span><a class="link" href="vmd_modifiers.html#variadic_macro_data.vmd_modifiers.vmd_modifiers_return_type.usage_with_other_modifiers_of_bo">Usage
with other modifiers of BOOST_VMD_ELEM</a>
</h5>
<p>
We have not yet discussed the rest of the modifiers which may be used with
BOOST_VMD_ELEM, but return type modifiers are completely independent of any
of them. This means they can be combined with other modifiers and whenever
the element of the sequence is returned the return type modifiers determine
of what the value of that element consists; whether it be just the element
data or the element as a type/data tuple with the type parsed according to
our return type modifier. When we subsequently discuss the use of other modifiers
with BOOST_VMD_ELEM and refer to the element being returned, we are referring
to that element as it is determined by the return type modifiers, which by
default only returns the element's data.
</p>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_generic/vmd_assert.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_modifiers/vmd_modifiers_filter.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,183 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Filtering modifiers</title>
<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../vmd_modifiers.html" title="Macros with modifiers">
<link rel="prev" href="../vmd_modifiers.html" title="Macros with modifiers">
<link rel="next" href="vmd_modifiers_identifier.html" title="Identifier modifiers">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../vmd_modifiers.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_modifiers.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_modifiers_identifier.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="variadic_macro_data.vmd_modifiers.vmd_modifiers_filter"></a><a class="link" href="vmd_modifiers_filter.html" title="Filtering modifiers">Filtering
modifiers</a>
</h3></div></div></div>
<p>
Filtering modifiers are optional modifiers which work with some generic macros
to specify a type of data to apply to the macro's functionality. The filtering
modifier itself is an optional parameter specified as a v-type. Any v-type,
specified as an optional parameter, may be used as a filtering modifier.
</p>
<h5>
<a name="variadic_macro_data.vmd_modifiers.vmd_modifiers_filter.h0"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_modifiers.vmd_modifiers_filter.usage_with_equality_macros"></a></span><a class="link" href="vmd_modifiers_filter.html#variadic_macro_data.vmd_modifiers.vmd_modifiers_filter.usage_with_equality_macros">Usage
with equality macros</a>
</h5>
<p>
The equality macros, BOOST_VMD_EQUAL and BOOST_VMD_NOT_EQUAL, tests generically
whether each of its two required inputs are equal or not equal to each other.
</p>
<p>
Each of these macro takes a single optional parameter, a filtering modifier,
to narrow the focus of its equality testing to a particular v-type.
</p>
<p>
For the macro BOOST_VMD_EQUAL this optional parameter when specified means
that equality is not only that the two required input parameters are equal
but also that they are of the type or of a subtype of the third optional
parameter. A number and a v-type are subtypes of identifiers while a non-empty
list and an array are subtypes of tuples.
</p>
<p>
Conversely BOOST_VMD_NOT_EQUAL, with the optional third v-type parameter,
returns 1 if either the first two parameters are not equal or if the type
of the first two parameters is not the type or a subtype of the third parameter.
Otherwise it returns 0. It is implemented as the complement of BOOST_VMD_EQUAL
so that whenever BOOST_VMD_EQUAL returns 1, BOOST_VMD_NOT_EQUAL returns 0
and vice versa.
</p>
<p>
Here is an example of using BOOST_VMD_EQUAL with a filtering modifier. BOOST_VMD_NOT_EQUAL
is just the complement of the results in our example for each result, and
would be redundant to be specified each time below.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">equal</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_AN_ID1</span> <span class="special">(</span><span class="identifier">AN_ID1</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_AN_ID2</span> <span class="special">(</span><span class="identifier">AN_ID2</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_AN_ID1_AN_ID1</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_AN_ID2_AN_ID2</span>
<span class="preprocessor">#define</span> <span class="identifier">AN_IDENTIFIER1</span> <span class="identifier">AN_ID1</span>
<span class="preprocessor">#define</span> <span class="identifier">AN_IDENTIFIER2</span> <span class="identifier">AN_ID2</span>
<span class="preprocessor">#define</span> <span class="identifier">AN_IDENTIFIER3</span> <span class="identifier">AN_ID1</span> <span class="comment">// same as AN_IDENTIFIER1 = AN_ID1</span>
<span class="preprocessor">#define</span> <span class="identifier">A_NUMBER1</span> <span class="number">33</span>
<span class="preprocessor">#define</span> <span class="identifier">A_NUMBER2</span> <span class="number">145</span>
<span class="preprocessor">#define</span> <span class="identifier">A_NUMBER3</span> <span class="number">33</span> <span class="comment">// same as A_NUMBER1 = 33</span>
<span class="preprocessor">#define</span> <span class="identifier">A_TUPLE1</span> <span class="special">(</span><span class="identifier">AN_IDENTIFIER1</span><span class="special">,</span><span class="identifier">A_NUMBER1</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">A_TUPLE2</span> <span class="special">(</span><span class="identifier">AN_IDENTIFIER1</span><span class="special">,</span><span class="identifier">A_NUMBER2</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">A_TUPLE3</span> <span class="special">(</span><span class="identifier">AN_IDENTIFIER3</span><span class="special">,</span><span class="identifier">A_NUMBER3</span><span class="special">)</span> <span class="comment">// same as A_TUPLE1 = (AN_ID1,33)</span>
<span class="preprocessor">#define</span> <span class="identifier">A_LIST1</span> <span class="special">(</span><span class="identifier">A_NUMBER1</span><span class="special">,(</span><span class="identifier">A_NUMBER3</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">))</span>
<span class="preprocessor">#define</span> <span class="identifier">A_LIST2</span> <span class="special">(</span><span class="identifier">A_NUMBER1</span><span class="special">,(</span><span class="identifier">A_NUMBER2</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">))</span>
<span class="preprocessor">#define</span> <span class="identifier">A_LIST3</span> <span class="special">(</span><span class="identifier">A_NUMBER1</span><span class="special">,(</span><span class="identifier">A_NUMBER3</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">))</span>
<span class="preprocessor">#define</span> <span class="identifier">A_LIST4</span> <span class="identifier">BOOST_PP_NIL</span> <span class="comment">// empty list</span>
<span class="preprocessor">#define</span> <span class="identifier">A_LIST5</span> <span class="identifier">BOOST_PP_NIL</span> <span class="comment">// empty list</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">AN_IDENTIFIER1</span><span class="special">,</span><span class="identifier">AN_IDENTIFIER2</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">AN_IDENTIFIER1</span><span class="special">,</span><span class="identifier">AN_IDENTIFIER3</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">AN_IDENTIFIER1</span><span class="special">,</span><span class="identifier">AN_IDENTIFIER3</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_TYPE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span> <span class="identifier">because</span> <span class="identifier">the</span> <span class="identifier">type</span> <span class="identifier">does</span> <span class="keyword">not</span> <span class="identifier">match</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_NUMBER1</span><span class="special">,</span><span class="identifier">A_NUMBER2</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_NUMBER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_NUMBER1</span><span class="special">,</span><span class="identifier">A_NUMBER3</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_NUMBER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_NUMBER1</span><span class="special">,</span><span class="identifier">A_NUMBER3</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span> <span class="identifier">because</span> <span class="identifier">a</span> <span class="identifier">number</span> <span class="identifier">is</span> <span class="identifier">an</span> <span class="identifier">identifier</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_NUMBER1</span><span class="special">,</span><span class="identifier">A_NUMBER3</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_EMPTY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span> <span class="identifier">because</span> <span class="identifier">the</span> <span class="identifier">type</span> <span class="identifier">does</span> <span class="keyword">not</span> <span class="identifier">match</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_TUPLE1</span><span class="special">,</span><span class="identifier">A_TUPLE2</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_TUPLE1</span><span class="special">,</span><span class="identifier">A_TUPLE3</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_TUPLE1</span><span class="special">,</span><span class="identifier">A_TUPLE3</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_ARRAY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span> <span class="identifier">because</span> <span class="identifier">the</span> <span class="identifier">type</span> <span class="identifier">does</span> <span class="keyword">not</span> <span class="identifier">match</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_LIST1</span><span class="special">,</span><span class="identifier">A_LIST2</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_LIST1</span><span class="special">,</span><span class="identifier">A_LIST3</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_LIST1</span><span class="special">,</span><span class="identifier">A_LIST3</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span> <span class="identifier">because</span> <span class="identifier">the</span> <span class="identifier">type</span> <span class="identifier">does</span> <span class="keyword">not</span> <span class="identifier">match</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_LIST1</span><span class="special">,</span><span class="identifier">A_LIST3</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span> <span class="identifier">because</span> <span class="identifier">a</span> <span class="identifier">non</span><span class="special">-</span><span class="identifier">empty</span> <span class="identifier">list</span> <span class="identifier">is</span> <span class="identifier">also</span> <span class="identifier">a</span> <span class="identifier">tuple</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_LIST4</span><span class="special">,</span><span class="identifier">A_LIST5</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_LIST4</span><span class="special">,</span><span class="identifier">A_LIST5</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span> <span class="identifier">because</span> <span class="identifier">an</span> <span class="identifier">empty</span> <span class="identifier">list</span> <span class="identifier">is</span> <span class="identifier">also</span> <span class="identifier">an</span> <span class="identifier">identifier</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_LIST4</span><span class="special">,</span><span class="identifier">A_LIST5</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span> <span class="identifier">because</span> <span class="identifier">an</span> <span class="identifier">empty</span> <span class="identifier">list</span> <span class="identifier">is</span> <span class="keyword">not</span> <span class="identifier">a</span> <span class="identifier">tuple</span>
</pre>
<h5>
<a name="variadic_macro_data.vmd_modifiers.vmd_modifiers_filter.h1"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_modifiers.vmd_modifiers_filter.usage_with_boost_vmd_elem"></a></span><a class="link" href="vmd_modifiers_filter.html#variadic_macro_data.vmd_modifiers.vmd_modifiers_filter.usage_with_boost_vmd_elem">Usage
with BOOST_VMD_ELEM</a>
</h5>
<p>
As with the equality macros BOOST_VMD_ELEM allows one to perform filtering
for the result. An optional parameter of a v-type can be used so that BOOST_VMD_ELEM
returns its result only if the sequence element is of the v-type specified,
else it fails to find the element in the same way that an element number
which is outside the bounds of the sequence fails.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">elem</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_ANAME</span> <span class="special">(</span><span class="identifier">ANAME</span><span class="special">)</span> <span class="comment">// an identifier must always be registered to be found by VMD</span>
<span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE</span> <span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">,</span><span class="number">3</span><span class="special">)</span> <span class="number">46</span> <span class="special">(</span><span class="identifier">list_data1</span><span class="special">,(</span><span class="identifier">list_data2</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">))</span> <span class="identifier">BOOST_VMD_TYPE_SEQ</span> <span class="identifier">ANAME</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">,</span><span class="number">3</span><span class="special">)</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">,</span><span class="number">3</span><span class="special">)</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_SEQ</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">emptiness</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">46</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_NUMBER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">46</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">46</span> <span class="identifier">since</span> <span class="identifier">a</span> <span class="identifier">number</span> <span class="identifier">is</span> <span class="identifier">also</span> <span class="identifier">an</span> <span class="identifier">identifier</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">emptiness</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">2</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="special">(</span><span class="identifier">list_data1</span><span class="special">,(</span><span class="identifier">list_data2</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">))</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">2</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="special">(</span><span class="identifier">list_data1</span><span class="special">,(</span><span class="identifier">list_data2</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">))</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">2</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="special">(</span><span class="identifier">list_data1</span><span class="special">,(</span><span class="identifier">list_data2</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">))</span> <span class="identifier">since</span> <span class="identifier">a</span> <span class="identifier">list</span> <span class="identifier">is</span> <span class="identifier">also</span> <span class="identifier">a</span> <span class="identifier">tuple</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">2</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_TYPE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">emptiness</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">3</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_SEQ</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">3</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_TYPE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_SEQ</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">3</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_SEQ</span> <span class="identifier">since</span> <span class="identifier">a</span> <span class="identifier">type</span> <span class="identifier">is</span> <span class="identifier">also</span> <span class="identifier">an</span> <span class="identifier">identifier</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">3</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">emptiness</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">4</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">ANAME</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">4</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">ANAME</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">4</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_NUMBER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">emptiness</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_PP_NIL</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_PP_NIL</span> <span class="identifier">since</span> <span class="identifier">it</span> <span class="identifier">is</span> <span class="identifier">an</span> <span class="identifier">empty</span> <span class="identifier">list</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_PP_NIL</span> <span class="identifier">since</span> <span class="identifier">it</span> <span class="identifier">a</span> <span class="identifier">registered</span> <span class="identifier">identifier</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">emptiness</span>
</pre>
<p>
If you specify more than one v-type as a filtering modifier to BOOST_VMD_ELEM
the last v-type becomes the filter.
</p>
<p>
Filtering with BOOST_VMD_ELEM denotes the type of the data expected when
the particular element is found. Because filtering represents the type of
the data requested, filtering modifiers and return type modifiers are mutually
exclusive and any filtering modifier means that return type modifiers specified
are ignored.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../vmd_modifiers.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_modifiers.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_modifiers_identifier.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,202 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Identifier modifiers</title>
<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../vmd_modifiers.html" title="Macros with modifiers">
<link rel="prev" href="vmd_modifiers_filter.html" title="Filtering modifiers">
<link rel="next" href="vmd_modifiers_splitting.html" title="Splitting modifiers">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_modifiers_filter.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_modifiers.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_modifiers_splitting.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="variadic_macro_data.vmd_modifiers.vmd_modifiers_identifier"></a><a class="link" href="vmd_modifiers_identifier.html" title="Identifier modifiers">Identifier
modifiers</a>
</h3></div></div></div>
<p>
Identifier modifiers are optional parameters which specify a set of identifiers
to search in order to look for a particular identifier match rather than
just any identifier.
</p>
<h5>
<a name="variadic_macro_data.vmd_modifiers.vmd_modifiers_identifier.h0"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_modifiers.vmd_modifiers_identifier.usage_with_boost_vmd_is_identifi"></a></span><a class="link" href="vmd_modifiers_identifier.html#variadic_macro_data.vmd_modifiers.vmd_modifiers_identifier.usage_with_boost_vmd_is_identifi">Usage
with BOOST_VMD_IS_IDENTIFIER</a>
</h5>
<p>
Once we have both registered and pre-detected an identifier we can test whether
an identifier is a particular identifier using BOOST_VMD_IS_IDENTIFER and
identifier modifiers. We do this by passing optional parameter(s) to BOOST_VMD_IS_IDENTIFER.
The optional parameter(s) are either a single tuple of possible identifiers
we are trying to match, or the individual identifiers themselves as separate
parameters.
</p>
<p>
Using the optional parameter(s) with BOOST_VMD_IS_IDENTIFER we are asking
not only if our input is any of the registered identifiers but also if it
is one of a number of pre-detected identifiers.
</p>
<p>
As an example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_identifier</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_yellow</span> <span class="special">(</span><span class="identifier">yellow</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_green</span> <span class="special">(</span><span class="identifier">green</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_blue</span> <span class="special">(</span><span class="identifier">blue</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_red</span> <span class="special">(</span><span class="identifier">red</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_yellow_yellow</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_green_green</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_blue_blue</span>
<span class="identifier">BOOST_VMD_IS_IDENTIFIER</span><span class="special">(</span><span class="identifier">some_input</span><span class="special">,</span><span class="identifier">yellow</span><span class="special">)</span> <span class="comment">// returns 1 only if 'some_input is 'yellow', else returns 0</span>
<span class="identifier">BOOST_VMD_IS_IDENTIFIER</span><span class="special">(</span><span class="identifier">some_input</span><span class="special">,</span><span class="identifier">yellow</span><span class="special">,</span><span class="identifier">blue</span><span class="special">)</span> <span class="comment">// returns 1 only if 'some_input is 'yellow' or 'blue', else returns 0</span>
<span class="identifier">BOOST_VMD_IS_IDENTIFIER</span><span class="special">(</span><span class="identifier">some_input</span><span class="special">,(</span><span class="identifier">yellow</span><span class="special">,</span><span class="identifier">green</span><span class="special">))</span> <span class="comment">// returns 1 if 'some_input' is 'yellow' or 'green', else returns 0</span>
<span class="identifier">BOOST_VMD_IS_IDENTIFIER</span><span class="special">(</span><span class="identifier">some_input</span><span class="special">,</span><span class="identifier">red</span><span class="special">)</span>
<span class="comment">// always returns 0, even if 'some_input' is 'red' since 'red' has not been pre-detected</span>
</pre>
<p>
whereas
</p>
<pre class="programlisting"><span class="identifier">BOOST_VMD_IS_IDENTIFIER</span><span class="special">(</span><span class="identifier">some_input</span><span class="special">)</span> <span class="comment">// returns 1 if 'some_input' is 'red' since 'red' has been registered</span>
</pre>
<p>
If you invoke BOOST_VMD_IS_IDENTIFIER with the optional parameter(s), the
invocation will only return 1 if the input matches one the identifier(s)
of the optional parameters and the identifier it matches has been registered
and pre-detected.
</p>
<p>
Both VMD numbers and v-types are identifier subtypes so you can also use
them as identifier modifiers. You do not have to register or pre-detect VMD
numbers or v-types since VMD has already done that for you.
</p>
<p>
As an example of using VMD numbers or v-types as identifier modifiers with
BOOST_VMD_IS_IDENTIFIER:
</p>
<pre class="programlisting"><span class="identifier">BOOST_VMD_IS_IDENTIFIER</span><span class="special">(</span><span class="identifier">some_input</span><span class="special">,</span><span class="number">1</span><span class="special">,</span><span class="number">3</span><span class="special">,</span><span class="number">5</span><span class="special">)</span> <span class="comment">// returns 1 only if 'some_input' is 1 or 3 or 5, else returns 0</span>
<span class="identifier">BOOST_VMD_IS_IDENTIFIER</span><span class="special">(</span><span class="identifier">some_input</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_TUPLE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_LIST</span><span class="special">,</span><span class="number">59</span><span class="special">)</span>
<span class="comment">// returns 1 only if 'some_input is the v-type BOOST_VMD_TYPE_TUPLE or the v-type BOOST_VMD_TYPE_LIST or 59, else returns 0</span>
</pre>
<h5>
<a name="variadic_macro_data.vmd_modifiers.vmd_modifiers_identifier.h1"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_modifiers.vmd_modifiers_identifier.usage_with_boost_vmd_elem"></a></span><a class="link" href="vmd_modifiers_identifier.html#variadic_macro_data.vmd_modifiers.vmd_modifiers_identifier.usage_with_boost_vmd_elem">Usage
with BOOST_VMD_ELEM</a>
</h5>
<p>
When we use the specific filter modifier BOOST_VMD_TYPE_IDENTIFIER as an
optional parameter of BOOST_VMD_ELEM we are asking for a particular element
of a sequence as long as it is a VMD identifier. With that specific filter
modifier BOOST_VMD_TYPE_IDENTIFIER we can use identifier modifiers to ask
for a particular element of a sequence as long as it matches one of our identifier
modifiers. If the specific filter modifier BOOST_VMD_TYPE_IDENTIFIER is not
being used then all identifier modifiers are ignored.
</p>
<p>
The syntax for specifying identifier modifiers using BOOST_VMD_ELEM is exactly
the same as the equivalent feature of the BOOST_VMD_IS_IDENTIFIER macro explained
just previously. Optional parameters in the form of identifiers can be specified
either singly any number of times or once as part of a tuple. For an identifier
found as a sequence element to match against one of these possible identifiers,
the possible identifiers must be both registered and pre-detected.
</p>
<p>
Since filter modifiers, which are v-types, are also identifiers, if you want
to use v-types as identifier modifiers you must use the form which places
all identifier modifiers as part of a tuple. Otherwise any v-types specified
singly as optional parameters are seen as filter modifiers and never as identifier
modifiers. VMD numbers are also identifiers and may be used as identifier
modifiers, but in this case VMD numbers as identifier modifiers do not need
to be part of a tuple to be detected.
</p>
<p>
Let's see how this works:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">elem</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_ANAME</span> <span class="special">(</span><span class="identifier">ANAME</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_APLACE</span> <span class="special">(</span><span class="identifier">APLACE</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_ACOUNTRY</span> <span class="special">(</span><span class="identifier">ACOUNTRY</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_ANAME_ANAME</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_APLACE_APLACE</span>
<span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE</span> <span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">,</span><span class="number">3</span><span class="special">)</span> <span class="identifier">ANAME</span> <span class="number">46</span> <span class="identifier">BOOST_VMD_TYPE_SEQ</span> <span class="identifier">ACOUNTRY</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'ANAME'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'ANAME'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">,</span><span class="identifier">APLACE</span><span class="special">,</span><span class="identifier">ACOUNTRY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">emptiness</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">,</span><span class="identifier">ANAME</span><span class="special">,</span><span class="identifier">APLACE</span><span class="special">,</span><span class="identifier">ACOUNTRY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'ANAME'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">,(</span><span class="identifier">APLACE</span><span class="special">,</span><span class="identifier">ACOUNTRY</span><span class="special">,</span><span class="identifier">ANAME</span><span class="special">))</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'ANAME'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">4</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'ACOUNTRY'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">4</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'ACOUNTRY'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">4</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">,</span><span class="identifier">ACOUNTRY</span><span class="special">,</span><span class="identifier">ANAME</span><span class="special">)</span>
<span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">emptiness</span> <span class="identifier">since</span> <span class="identifier">ACOUNTRY</span> <span class="identifier">is</span> <span class="keyword">not</span> <span class="identifier">pre</span><span class="special">-</span><span class="identifier">detected</span>
</pre>
<p>
Let us illustrate the case where VMD identifiers can be represented as either
filter modifiers or identifier modifiers.
</p>
<p>
Using the sequence above:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">elem</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">3</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">the</span> <span class="identifier">BOOST_VMD_TYPE_SEQ</span> <span class="identifier">type</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">3</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">)</span>
<span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">the</span> <span class="identifier">BOOST_VMD_TYPE_SEQ</span> <span class="identifier">type</span> <span class="identifier">since</span> <span class="identifier">a</span> <span class="identifier">type</span> <span class="identifier">is</span> <span class="identifier">an</span> <span class="identifier">identifier</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">3</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_SEQ</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">emptiness</span>
</pre>
<p>
The last use of our macro returns emptiness because if there is more than
one type specified as an optional parameter the last type is chosen for filtering.
Since the last type for type filtering is BOOST_VMD_TYPE_TUPLE and our fourth
element is a v-type and not a tuple, emptiness is returned. The syntax does
not specifying filtering with identifiers as might be supposed since BOOST_VMD_TYPE_SEQ
and BOOST_VMD_TYPE_TUPLE are not treated as identifier modifiers but rather
as additional filter modifiers.
</p>
<p>
In order to do filtering with an identifier and do it against various types
themselves, since v-types are identifiers, we must use the tuple form to
specify our identifier modifiers:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">elem</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">3</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">,(</span><span class="identifier">BOOST_VMD_TYPE_SEQ</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_TUPLE</span><span class="special">))</span>
<span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">BOOST_VMD_TYPE_SEQ</span>
</pre>
<p>
Now BOOST_VMD_TYPE_SEQ and BOOST_VMD_TYPE_TUPLE are treated as identifiers
modifiers to match against.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_modifiers_filter.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_modifiers.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_modifiers_splitting.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,119 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Index modifiers</title>
<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../vmd_modifiers.html" title="Macros with modifiers">
<link rel="prev" href="vmd_modifiers_splitting.html" title="Splitting modifiers">
<link rel="next" href="vmd_modifiers_single.html" title="Modifiers and the single-element sequence">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_modifiers_splitting.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_modifiers.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_modifiers_single.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="variadic_macro_data.vmd_modifiers.vmd_modifiers_index"></a><a class="link" href="vmd_modifiers_index.html" title="Index modifiers">Index
modifiers</a>
</h3></div></div></div>
<p>
Index modifiers can be used with the BOOST_VMD_ELEM macro when identifier
modifiers are being used. Index modifiers take two values:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
BOOST_VMD_RETURN_INDEX, return an index as a number, starting with 0,
of the particular identifier modifier which matched, as part of the output
of the BOOST_VMD_ELEM macro. If no particular identifier modifier matches,
return emptiness as part of the output. The index number is determined
purely by the order in which identifier modifiers are specified as optional
parameters to BOOST_VMD_ELEM, whether singly as individual optional parameters
or as a tuple of identifier modifiers.
</li>
<li class="listitem">
BOOST_VMD_RETURN_NO_INDEX, do not return an index as part of the output.
This is the default value and need only be used to override the BOOST_VMD_RETURN_INDEX
value if it is specified.
</li>
</ul></div>
<p>
The BOOST_VMD_RETURN_INDEX tells the programmer which one of the identifier
modifiers matched the element's data as an index. Some macro programmers
find this more useful for the purposes of macro branching logic than branching
using the actual name of the identifier itself.
</p>
<p>
When the index modifier BOOST_VMD_RETURN_INDEX is specified, and identifier
modifiers are specified along with the BOOST_VMD_TYPE_IDENTIFIER filter modifier,
the output of BOOST_VMD_ELEM becomes a tuple of two elements. The first tuple
element is the element matched and the last tuple element is the index, starting
with 0, of the identifier modifier which matched. If an element is not matched
both tuple elements are empty.
</p>
<p>
If the splitting modifier BOOST_VMD_RETURN_AFTER is also specified then the
output is a tuple of three elements. The first tuple element is the element
matched, the second tuple element is the rest of the sequence after the matching
element, and the last tuple element is the numeric index. If an element is
not matched then all three tuple elements are empty.
</p>
<p>
If identifier modifiers and the BOOST_VMD_TYPE_IDENTIFIER filter modifier
are not specified as optional parameters, then if BOOST_VMD_RETURN_INDEX
is specified it is ignored. If the splitting modifier BOOST_VMD_RETURN_ONLY_AFTER
is specified, if BOOST_VMD_RETURN_INDEX is also specified it is ignored.
</p>
<p>
Let's see how this works:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">elem</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_ANAME</span> <span class="special">(</span><span class="identifier">ANAME</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_APLACE</span> <span class="special">(</span><span class="identifier">APLACE</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_ACOUNTRY</span> <span class="special">(</span><span class="identifier">ACOUNTRY</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_ANAME_ANAME</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_APLACE_APLACE</span>
<span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE</span> <span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">,</span><span class="number">3</span><span class="special">)</span> <span class="identifier">ANAME</span> <span class="special">(</span><span class="number">1</span><span class="special">)(</span><span class="number">2</span><span class="special">)</span> <span class="number">46</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'ANAME'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">,</span><span class="identifier">APLACE</span><span class="special">,</span><span class="identifier">ACOUNTRY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">emptiness</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_INDEX</span><span class="special">,</span><span class="identifier">APLACE</span><span class="special">,</span><span class="identifier">ACOUNTRY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="special">(,)</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_INDEX</span><span class="special">,</span><span class="identifier">ANAME</span><span class="special">,</span><span class="identifier">APLACE</span><span class="special">,</span><span class="identifier">ACOUNTRY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(ANAME,0)'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_INDEX</span><span class="special">,(</span><span class="identifier">APLACE</span><span class="special">,</span><span class="identifier">ACOUNTRY</span><span class="special">,</span><span class="identifier">ANAME</span><span class="special">))</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(ANAME,2)'</span>
</pre>
<p>
Used with splitting modifiers:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">elem</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_INDEX</span><span class="special">,</span><span class="identifier">APLACE</span><span class="special">,</span><span class="identifier">ACOUNTRY</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_AFTER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="special">(,,)</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_INDEX</span><span class="special">,</span><span class="identifier">ANAME</span><span class="special">,</span><span class="identifier">APLACE</span><span class="special">,</span><span class="identifier">ACOUNTRY</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_AFTER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(ANAME,(1)(2) 46,0)'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_INDEX</span><span class="special">,(</span><span class="identifier">APLACE</span><span class="special">,</span><span class="identifier">ACOUNTRY</span><span class="special">,</span><span class="identifier">ANAME</span><span class="special">),</span><span class="identifier">BOOST_VMD_RETURN_AFTER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(ANAME,(1)(2) 46,2)'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_INDEX</span><span class="special">,(</span><span class="identifier">APLACE</span><span class="special">,</span><span class="identifier">ACOUNTRY</span><span class="special">,</span><span class="identifier">ANAME</span><span class="special">),</span><span class="identifier">BOOST_VMD_RETURN_ONLY_AFTER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(1)(2) 46'</span>
</pre>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_modifiers_splitting.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_modifiers.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_modifiers_single.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,72 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Modifiers and the single-element sequence</title>
<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../vmd_modifiers.html" title="Macros with modifiers">
<link rel="prev" href="vmd_modifiers_index.html" title="Index modifiers">
<link rel="next" href="../vmd_identifier_subtype.html" title="Identifier subtypes">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_modifiers_index.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_modifiers.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../vmd_identifier_subtype.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="variadic_macro_data.vmd_modifiers.vmd_modifiers_single"></a><a class="link" href="vmd_modifiers_single.html" title="Modifiers and the single-element sequence">Modifiers
and the single-element sequence</a>
</h3></div></div></div>
<p>
A single element sequence is what we normally think of when working with
macro data. It is a single type of macro data passed as an input parameter
to some macro and processed as such.
</p>
<p>
In its basic form without modifiers BOOST_VMD_ELEM serves to just return
a particular element of a sequence. For a single element sequence BOOST_VMD_ELEM
with element number 0, just returns the single-element sequence itself. This
does not offer much functionality for our simple sequence. However with modifiers
we can do things generically with our single-element sequence which correspond
to working with a single type of data and extracting information about it.
</p>
<p>
With the return type modifier we can get the type of the data along with
the data. Of course we can also use BOOST_VMD_GET_TYPE to retrieve just the
type of data.
</p>
<p>
With our filter modifier we can retrieve the data only if it is a particular
type, else retrieve emptiness.
</p>
<p>
With the identifier modifier we can retrieve an identifier only if it matches
one or more other identifiers, else retrieve emptiness.
</p>
<p>
With our index modifier we can retrieve both our identifier and its numeric
index if it matches one or more other identifiers, else retrieve a tuple
of two empty elements if no match is found.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_modifiers_index.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_modifiers.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../vmd_identifier_subtype.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,111 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Splitting modifiers</title>
<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../vmd_modifiers.html" title="Macros with modifiers">
<link rel="prev" href="vmd_modifiers_identifier.html" title="Identifier modifiers">
<link rel="next" href="vmd_modifiers_index.html" title="Index modifiers">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_modifiers_identifier.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_modifiers.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_modifiers_index.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="variadic_macro_data.vmd_modifiers.vmd_modifiers_splitting"></a><a class="link" href="vmd_modifiers_splitting.html" title="Splitting modifiers">Splitting
modifiers</a>
</h3></div></div></div>
<p>
The BOOST_VMD_ELEM macro, which by default just returns an element of a sequence,
has a usage where you can have it return both the element and the remaining
part of the sequence after the element, or even just the remaining part of
the sequence after the element by itself. This offers a form of splitting
the sequence on a particular element. When used to return the remaining part
of a sequence the remaining data may subsequently be treated as a VMD sequence
again.
</p>
<p>
To do this another set of optional modifiers are used which will be called
'splitting modifers'. These modifiers are:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
BOOST_VMD_RETURN_AFTER, which returns both the element information and
the rest of the sequence after the element as a two-element tuple
</li>
<li class="listitem">
BOOST_VMD_RETURN_ONLY_AFTER, which returns only the rest of the sequence
after the element specified
</li>
<li class="listitem">
BOOST_VMD_RETURN_NO_AFTER, this is the internal default which only returns
the element itself. It need never be specified but may be used to override
a previous splitting modifier specified as an optional parameter.
</li>
</ul></div>
<p>
If more than one of the splitting modifiers are specified as optional parameters
to BOOST_VMD_ELEM the last one specified is in effect.
</p>
<p>
The splitting modifiers BOOST_VMD_RETURN_NO_AFTER and BOOST_VMD_RETURN_AFTER
work with either return type modifiers or filtering modifiers if they are
used. The splitting modifier BOOST_VMD_RETURN_ONLY_AFTER works with filtering
modifiers if it is used and any return type modifiers will be ignored. Optional
modifiers may occur in any order after the required parameters to BOOST_VMD_ELEM.
</p>
<p>
If BOOST_VMD_RETURN_AFTER is in effect and an element is not found, either
because the element number is out of range for the sequence or because filtering
does not match the element type, a tuple will still be returned but both
its elements will be empty.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">elem</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_ANAME</span> <span class="special">(</span><span class="identifier">ANAME</span><span class="special">)</span> <span class="comment">// an identifier must always be registered to be found by VMD</span>
<span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE</span> <span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">,</span><span class="number">3</span><span class="special">)</span> <span class="number">46</span> <span class="special">(</span><span class="identifier">list_data1</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">)</span> <span class="identifier">BOOST_VMD_TYPE_SEQ</span> <span class="identifier">ANAME</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">2</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(list_data1,BOOST_PP_NIL)'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">2</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_NO_AFTER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(list_data1,BOOST_PP_NIL)'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">2</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_AFTER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'((list_data1,BOOST_PP_NIL),BOOST_VMD_TYPE_SEQ ANAME)'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">2</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_ONLY_AFTER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'BOOST_VMD_TYPE_SEQ ANAME'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">5</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">emptiness</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">5</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_NO_AFTER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">emptiness</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">5</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_AFTER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(,)'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">5</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_ONLY_AFTER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">emptiness</span>
</pre>
<p>
Combining splitting modifiers with return type modifiers:
</p>
<pre class="programlisting"><span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">2</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_AFTER</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'((BOOST_VMD_TYPE_LIST,(list_data1,BOOST_PP_NIL)),BOOST_VMD_TYPE_SEQ ANAME)'</span>
</pre>
<p>
Combining splitting modifiers with filtering modifiers:
</p>
<pre class="programlisting"><span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">2</span><span class="special">,</span><span class="identifier">A_SEQUENCE</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_AFTER</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'((list_data1,BOOST_PP_NIL),BOOST_VMD_TYPE_SEQ ANAME)'</span>
</pre>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_modifiers_identifier.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_modifiers.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_modifiers_index.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,107 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Naming conventions</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="prev" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="next" href="vmd_whyhow.html" title="Why and how to use">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../index.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_whyhow.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="variadic_macro_data.vmd_naming"></a><a class="link" href="vmd_naming.html" title="Naming conventions">Naming conventions</a>
</h2></div></div></div>
<p>
All of the macros in the library begin with the prefix BOOST_VMD_, where VMD
stands for 'Variadic Macro Data'.
</p>
<p>
Following the prefix, certain names in the macros refer to data types in this
library or Boost PP. These names and their data types are:
</p>
<div class="orderedlist"><ol class="orderedlist" type="1">
<li class="listitem">
TUPLE = Boost PP tuple data type.
</li>
<li class="listitem">
ARRAY = Boost PP array data type.
</li>
<li class="listitem">
LIST = Boost PP list data type.
</li>
<li class="listitem">
SEQ = Boost PP seq data type.
</li>
<li class="listitem">
IDENTIFIER = A VMD identifier
</li>
<li class="listitem">
NUMBER = A VMD number
</li>
<li class="listitem">
TYPE = A VMD type
</li>
</ol></div>
<p>
I have used most of these names in order to mimic the naming of Boost PP as
closely as possible. Subsequent use of the words 'array', 'list', 'seq', and
'tuple' refer to these Boost PP data types unless otherwise noted. See the
help for Boost PP for any explanation of these data types.
</p>
<p>
The term 'sequence' refers to a sequence of VMD data types and is not the same
as a Boost PP sequence which is always referred to in this documentation as
a 'seq'.
</p>
<p>
The term 'return' refers to the expansion of a macro. I use the terminology
of a macro "returning some data" rather than the terminology of a
macro "expanding to some data", even if the latter is more accurate,
because it more closely corresponds to the way I believe C++ programmers think
about macro programming.
</p>
<p>
The term 'emptiness' refers to no preprocessor data being passed to or returned
from a macro. I have avoided the word 'nothing' because it has too vague a
meaning.
</p>
<p>
The term 'data type' refers to the various preprocessor input types which VMD
can parse and which are listed above, also including emptiness.
</p>
<p>
The term 'v-type' refers to a VMD type, the term 'number' returns to a VMD
number and the term 'identifier' refers to a VMD identifier. All these will
be explained in their proper place.
</p>
<p>
The term "UB" stands for "undefined behavior" as it is
specified in the C++ standard.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../index.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_whyhow.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,161 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Boost PP re-entrant versions</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="prev" href="vmd_internal_macros.html" title="Controlling internal usage">
<link rel="next" href="vmd_dynamic_typing.html" title="Input as dynamic types">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_internal_macros.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_dynamic_typing.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="variadic_macro_data.vmd_reentrant"></a><a class="link" href="vmd_reentrant.html" title="Boost PP re-entrant versions">Boost PP re-entrant
versions</a>
</h2></div></div></div>
<p>
Nearly all macros in VMD have equivalent reentrant versions which are meant
to be used in a BOOST_PP_WHILE loop. These are versions which have an underscore
D suffix, take the next available BOOST_PP_WHILE iteration as their first parameter,
and then have the exact same functionality as their unsuffixed equivalents.
They can be used in BOOST_PP_WHILE loops to provide slightly quicker preprocessing
but, as the documentation for BOOST_PP_WHILE and BOOST_PP_WHILE_##d explain,
they do not have to be used.
</p>
<p>
These macros are:
</p>
<p>
Arrays
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
BOOST_VMD_IS_ARRAY_D
</li>
<li class="listitem">
BOOST_VMD_IS_EMPTY_ARRAY_D
</li>
<li class="listitem">
BOOST_VMD_ASSERT_IS_ARRAY_D
</li>
</ul></div>
<p>
Identifiers
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
BOOST_VMD_IS_IDENTIFIER_D
</li>
<li class="listitem">
BOOST_VMD_ASSERT_IS_IDENTIFIER_D
</li>
</ul></div>
<p>
Lists
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
BOOST_VMD_IS_LIST_D
</li>
<li class="listitem">
BOOST_VMD_IS_EMPTY_LIST_D
</li>
<li class="listitem">
BOOST_VMD_ASSERT_IS_LIST_D
</li>
</ul></div>
<p>
Sequences
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
BOOST_VMD_ELEM_D
</li>
<li class="listitem">
BOOST_VMD_ENUM_D
</li>
<li class="listitem">
BOOST_VMD_EQUAL_D
</li>
<li class="listitem">
BOOST_VMD_GET_TYPE_D
</li>
<li class="listitem">
BOOST_VMD_IS_MULTI_D
</li>
<li class="listitem">
BOOST_VMD_IS_UNARY_D
</li>
<li class="listitem">
BOOST_VMD_NOT_EQUAL_D
</li>
<li class="listitem">
BOOST_VMD_SIZE_D
</li>
<li class="listitem">
BOOST_VMD_TO_ARRAY_D
</li>
<li class="listitem">
BOOST_VMD_TO_LIST_D
</li>
<li class="listitem">
BOOST_VMD_TO_SEQ_D
</li>
<li class="listitem">
BOOST_VMD_TO_TUPLE_D
</li>
</ul></div>
<p>
Seqs
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
BOOST_VMD_IS_SEQ_D
</li>
<li class="listitem">
BOOST_VMD_ASSERT_IS_SEQ_D
</li>
</ul></div>
<p>
Types
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
BOOST_VMD_IS_TYPE_D
</li>
<li class="listitem">
BOOST_VMD_ASSERT_IS_TYPE_D
</li>
</ul></div>
<p>
Other
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
BOOST_VMD_IS_PARENS_EMPTY_D
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_internal_macros.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_dynamic_typing.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,470 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Specific macros for working with data types</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="prev" href="vmd_data_types.html" title="Data types">
<link rel="next" href="vmd_specific/vmd_constraints.html" title="Macro constraints">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_data_types.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_specific/vmd_constraints.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="variadic_macro_data.vmd_specific"></a><a class="link" href="vmd_specific.html" title="Specific macros for working with data types">Specific macros for working
with data types</a>
</h2></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="vmd_specific.html#variadic_macro_data.vmd_specific.vmd_test_empty">Emptiness</a></span></dt>
<dt><span class="section"><a href="vmd_specific/vmd_constraints.html">Macro
constraints</a></span></dt>
<dt><span class="section"><a href="vmd_specific/vmd_identifier.html">Identifiers</a></span></dt>
<dt><span class="section"><a href="vmd_specific/vmd_number.html">Numbers</a></span></dt>
<dt><span class="section"><a href="vmd_specific/vmd_type.html">Types</a></span></dt>
<dt><span class="section"><a href="vmd_specific/vmd_pp_data_types.html">VMD
and Boost PP data types</a></span></dt>
<dt><span class="section"><a href="vmd_specific/vmd_identifying.html">Identifying
data types</a></span></dt>
</dl></div>
<p>
VMD has a number of specific macros for parsing data types. Each of these macros
asks if some input is a particular VMD data type.
</p>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="variadic_macro_data.vmd_specific.vmd_test_empty"></a><a class="link" href="vmd_specific.html#variadic_macro_data.vmd_specific.vmd_test_empty" title="Emptiness">Emptiness</a>
</h3></div></div></div>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_test_empty.h0"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_test_empty.passing_empty_arguments"></a></span><a class="link" href="vmd_specific.html#variadic_macro_data.vmd_specific.vmd_test_empty.passing_empty_arguments">Passing
empty arguments</a>
</h5>
<p>
It is possible to pass an empty argument to a macro. The official terminology
for this in the C++ standard is an argument "consisting of no preprocessing
tokens".
</p>
<p>
Let us consider a number of cases without worrying too much what the macro
output represents.
</p>
<p>
Consider these two function-like macros:
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">SMACRO</span><span class="special">()</span> <span class="identifier">someoutput</span>
<span class="preprocessor">#define</span> <span class="identifier">EMACRO</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span> <span class="identifier">otheroutput</span> <span class="identifier">x</span>
</pre>
<p>
The first macro takes no parameters so invoking it must always be done by
</p>
<pre class="programlisting"><span class="identifier">SMACRO</span><span class="special">()</span>
</pre>
<p>
and passing any arguments to it would be invalid.
</p>
<p>
The second macro takes a single parameter. it can be evoked as
</p>
<pre class="programlisting"><span class="identifier">EMACRO</span><span class="special">(</span><span class="identifier">somedata</span><span class="special">)</span>
</pre>
<p>
but it also can be invoked as
</p>
<pre class="programlisting"><span class="identifier">EMACRO</span><span class="special">()</span>
</pre>
<p>
In the second invocation of EMACRO we are passing an empty argument to the
macro. Similarly for any macro having 1 or more parameters, an empty argument
can be validly passed for any of the parameters, as in
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">MMACRO</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier">y</span><span class="special">,</span><span class="identifier">z</span><span class="special">)</span> <span class="identifier">x</span> <span class="identifier">y</span> <span class="identifier">z</span>
<span class="identifier">MMACRO</span><span class="special">(</span><span class="number">1</span><span class="special">,,</span><span class="number">2</span><span class="special">)</span>
</pre>
<p>
An empty argument is an argument even if we are passing nothing.
</p>
<p>
Because an empty argument can be passed for a given parameter of a macro
does not mean one should do so. Any given macro will specify what each argument
to a macro should represent, and it is has normally been very rare to encounter
a macro which specifies that an empty argument can logically be passed for
a given argument. But from the perspective of standard C++ it is perfectly
valid to pass an empty argument for a macro parameter.
</p>
<p>
The notion of passing empty arguments can be extended to passing empty data
which "consists of no preprocessing tokens" in slightly more complicated
situations. It is possible to pass empty data as an argument to a variadic
macro in the form of variadic macro data, as in
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">VMACRO</span><span class="special">(</span><span class="identifier">x</span><span class="special">,...)</span> <span class="identifier">x</span> <span class="identifier">__VA_ARGS__</span>
</pre>
<p>
invoked as
</p>
<pre class="programlisting"><span class="identifier">VMACRO</span><span class="special">(</span><span class="identifier">somedata</span><span class="special">,)</span>
</pre>
<p>
Here one passes empty data as the variadic macro data and it is perfectly
valid C++. Please notice that this different from
</p>
<pre class="programlisting"><span class="identifier">VMACRO</span><span class="special">(</span><span class="identifier">somedata</span><span class="special">)</span>
</pre>
<p>
which is not valid C++ since something must be passed for the variadic argument.
Similar one could invoke the macro as
</p>
<pre class="programlisting"><span class="identifier">VMACRO</span><span class="special">(</span><span class="identifier">somedata</span><span class="special">,</span><span class="identifier">vdata1</span><span class="special">,,</span><span class="identifier">vdata3</span><span class="special">)</span>
</pre>
<p>
where one is passing variadic macro data but an element in the variadic macro
data is empty.
</p>
<p>
Furthermore if we are invoking a macro which expects a Boost PP data type,
such as a tuple, we could also validly pass empty data for all or part of
the data in a tuple, as in
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">TMACRO</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier">atuple</span><span class="special">)</span> <span class="identifier">x</span> <span class="identifier">atuple</span>
<span class="identifier">TMACRO</span><span class="special">(</span><span class="identifier">somedata</span><span class="special">,())</span>
</pre>
<p>
In this case we are passing a 1 element tuple where the single element itself
is empty.
</p>
<p>
or
</p>
<pre class="programlisting"><span class="identifier">TMACRO</span><span class="special">(</span><span class="identifier">somedata</span><span class="special">,(</span><span class="identifier">telem1</span><span class="special">,,</span><span class="identifier">telem2</span><span class="special">,</span><span class="identifier">teleem3</span><span class="special">))</span>
</pre>
<p>
In this case we are passing a 4 element tuple where the second element is
empty.
</p>
<p>
Again either invocation is valid C++ but it is not necessarily what the designed
of the macro has desired, even if in both cases the macro designer has specified
that the second parameter must be a tuple for the macro to work properly.
</p>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_test_empty.h1"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_test_empty.returning_emptiness"></a></span><a class="link" href="vmd_specific.html#variadic_macro_data.vmd_specific.vmd_test_empty.returning_emptiness">Returning
emptiness</a>
</h5>
<p>
Similar to passing empty arguments in various ways to a macro, the data which
a macro returns ( or 'generates' may be a better term ) could be empty, in
various ways. Again I am not necessarily promoting this idea as a common
occurrence of macro design but merely pointing it out as valid C++ preprocessing.
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">RMACRO</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier">y</span><span class="special">,</span><span class="identifier">z</span><span class="special">)</span>
<span class="identifier">RMACRO</span><span class="special">(</span><span class="identifier">data1</span><span class="special">,</span><span class="identifier">data2</span><span class="special">,</span><span class="identifier">data3</span><span class="special">)</span>
</pre>
<p>
It is perfectly valid C++ to return "nothing" from a macro invocation.
In fact a number of macros in Boost PP do that based on the preprocessor
metaprogramming logic of the macro, and are documented as such.
</p>
<p>
Similarly one could return nothing as part or all of a Boost PP data type
or even as part of variadic macro data.
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">TRETMACRO</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier">y</span><span class="special">,</span><span class="identifier">z</span><span class="special">)</span> <span class="special">()</span>
<span class="preprocessor">#define</span> <span class="identifier">TRETMACRO1</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier">y</span><span class="special">,</span><span class="identifier">z</span><span class="special">)</span> <span class="special">(</span><span class="identifier">x</span><span class="special">,,</span><span class="identifier">y</span><span class="special">,,</span><span class="identifier">z</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">VRETMACRO</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier">y</span><span class="special">,</span><span class="identifier">z</span><span class="special">)</span> <span class="identifier">x</span><span class="special">,,</span><span class="identifier">y</span><span class="special">,,</span><span class="identifier">z</span>
</pre>
<p>
Here again we are returning something but in terms of a Boost PP tuple or
in terms of variadic data, we have elements which are empty.
</p>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_test_empty.h2"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_test_empty.emptiness_in_preprocessor_metapr"></a></span><a class="link" href="vmd_specific.html#variadic_macro_data.vmd_specific.vmd_test_empty.emptiness_in_preprocessor_metapr">Emptiness
in preprocessor metaprogramming</a>
</h5>
<p>
In the examples given above where "emptiness" in one form of another
is passed as arguments to a macro or returned from a macro, the examples
I have given were created as simplified as possible to illustrate my points.
In actual preprocessor metaprogramming, using Boost PP, where complicated
logic is used to generate macro output based on the arguments to a macro,
it might be useful to allow and work with empty data if one were able to
test for the fact that data was indeed empty.
</p>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_test_empty.h3"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_test_empty.testing_for_empty_data"></a></span><a class="link" href="vmd_specific.html#variadic_macro_data.vmd_specific.vmd_test_empty.testing_for_empty_data">Testing
for empty data</a>
</h5>
<p>
Currently Boost PP has an undocumented macro for testing whether a parameter
is empty of not, written without the use of variadic macros. The macro is
called BOOST_PP_IS_EMPTY. The macro is by its nature flawed, since there
is no generalized way of determining whether or not a parameter is empty
using the C++ preprocessor. But the macro will work given input limited in
various ways or if the input is actually empty.
</p>
<p>
Paul Mensonides, the developer of Boost PP and the BOOST_PP_IS_EMPTY macro
in that library, also wrote a better macro using variadic macros, for determining
whether or not a parameter is empty or not, which he published on the Internet
in response to a discussion about emptiness. This macro is also not perfect,
since there is no perfect solution, but will work correctly with almost all
input. I have adapted his code for the VMD and developed my own very slightly
different code.
</p>
<p>
The macro is called <code class="computeroutput"><a class="link" href="../BOOST_VMD_IS_EMPTY.html" title="Macro BOOST_VMD_IS_EMPTY">BOOST_VMD_IS_EMPTY</a></code>
and will return 1 if its input is empty or 0 if its input is not empty. The
macro is a variadic macro which make take any input <a href="#ftn.variadic_macro_data.vmd_specific.vmd_test_empty.f0" class="footnote" name="variadic_macro_data.vmd_specific.vmd_test_empty.f0"><sup class="footnote">[1]</sup></a>.
</p>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_test_empty.h4"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_test_empty.macro_flaw_with_a_standard_c_com"></a></span><a class="link" href="vmd_specific.html#variadic_macro_data.vmd_specific.vmd_test_empty.macro_flaw_with_a_standard_c_com">Macro
Flaw with a standard C++ compiler</a>
</h5>
<p>
The one situation where the macro always does not work properly is if its
input resolves to a function-like macro name or a sequence of preprocessor
tokens ending with a function-like macro name and the function-like macro
takes two or more parameters.
</p>
<p>
Here is a simple example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_empty</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">FMACRO</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier">y</span><span class="special">)</span> <span class="identifier">any_output</span>
<span class="identifier">BOOST_VMD_IS_EMPTY</span><span class="special">(</span><span class="identifier">FMACRO</span><span class="special">)</span>
<span class="identifier">BOOST_VMD_IS_EMPTY</span><span class="special">(</span><span class="identifier">some_input</span> <span class="identifier">FMACRO</span><span class="special">)</span>
</pre>
<p>
In the first case the name of a function-like macro is being passed to BOOST_VMD_IS_EMPTY
while in the second case a sequence of preprocessing tokens is being passed
to BOOST_VMD_IS_EMPTY ending with the name of a function-like macro. The
function-like macro also has two ( or more ) parameters. In both the cases
above a compiler error will result from the use of BOOST_VMD_IS_EMPTY.
</p>
<p>
Please note that these two problematical cases are not the same as passing
an invocation of a function-like macro name to BOOST_VMD_IS_EMPTY, as in
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_empty</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_VMD_IS_EMPTY</span><span class="special">(</span><span class="identifier">FMACRO</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">,</span><span class="identifier">arg2</span><span class="special">))</span>
<span class="identifier">BOOST_VMD_IS_EMPTY</span><span class="special">(</span><span class="identifier">someinput</span> <span class="identifier">FMACRO</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">,</span><span class="identifier">arg2</span><span class="special">))</span>
</pre>
<p>
which always works correctly, unless of course a particular function-like
macro invocation resolves to either of our two previous situations.
</p>
<p>
Another situation where the macro may not work properly is if the previously
mentioned function-like macro takes a single parameter but creates an error
when the argument passed is empty. An example of this would be:
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">FMACRO</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span> <span class="identifier">BOOST_PP_CAT</span><span class="special">(+,</span><span class="identifier">x</span> <span class="identifier">C</span><span class="special">);</span>
</pre>
<p>
When nothing is passed to FMACRO undefined behavior will occur since attempting
to concatenate '+' to ' C' is UB in C++ preprocessor terms.
</p>
<p>
So for a standard conforming compiler we have essentially a single corner
case where the BOOST_VMD_IS_EMPTY does not work and, when it does not work
it, produces a compiler error rather than an incorrect result. Essentially
what is desired for maximum safety is that we never pass input ending with
the name of a function-like macro name when testing for emptiness.
</p>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_test_empty.h5"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_test_empty.macro_flaw_with_visual_c"></a></span><a class="link" href="vmd_specific.html#variadic_macro_data.vmd_specific.vmd_test_empty.macro_flaw_with_visual_c">Macro
Flaw with Visual C++</a>
</h5>
<p>
The VC++ preprocessor is not a standard C++ conforming preprocessor in at
least two relevant situations to our discussion of emptiness. These situations
combine to create a single corner case which causes the BOOST_VMD_IS_EMPTY
macro to not work properly using VC++ when the input resolves to a function-like
macro name.
</p>
<p>
The first situation, related to our discussion of emptiness, where the VC++
preprocessor is not a standard C++ conforming preprocessor is that if a macro
taking 'n' number of parameters is invoked with 0 to 'n-1' parameters, the
compiler does not give an error, but only a warning.
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">FMACRO</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier">y</span><span class="special">)</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span>
<span class="identifier">FMACRO</span><span class="special">(</span><span class="number">1</span><span class="special">)</span>
</pre>
<p>
should give a compiler error, as it does when using a C++ standard-conforming
compiler, but when invoked using VC++ it only gives a warning and VC++ continues
macro substitution with 'y' as a placemarker preprocessing token. This non-standard
conforming action actually eliminates the case where BOOST_VMD_IS_EMPTY does
not work properly with a standard C++ conforming compiler. But of course
it has the potential of producing incorrect output in other macro processing
situations unrelated to the BOOST_VMD_IS_EMPTY invocation, where a compiler
error should occur.
</p>
<p>
A second general situation, related to our discussion of emptiness, where
the VC++ preprocessor is not a standard C++ conforming preprocessor is that
the expansion of a macro works incorrectly when the expanded macro is a function-like
macro name followed by a function-like macro invocation, in which case the
macro re-expansion is erroneously done more than once. This latter case can
be seen by this example:
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">FMACRO1</span><span class="special">(</span><span class="identifier">parameter</span><span class="special">)</span> <span class="identifier">FMACRO3</span> <span class="identifier">parameter</span><span class="special">()</span>
<span class="preprocessor">#define</span> <span class="identifier">FMACRO2</span><span class="special">()</span> <span class="special">()</span>
<span class="preprocessor">#define</span> <span class="identifier">FMACRO3</span><span class="special">()</span> <span class="number">1</span>
<span class="identifier">FMACRO1</span><span class="special">(</span><span class="identifier">FMACRO2</span><span class="special">)</span>
<span class="identifier">should</span> <span class="identifier">expand</span> <span class="identifier">to</span><span class="special">:</span>
<span class="identifier">FMACRO3</span><span class="special">()</span>
<span class="identifier">but</span> <span class="identifier">in</span> <span class="identifier">VC</span><span class="special">++</span> <span class="identifier">it</span> <span class="identifier">expands</span> <span class="identifier">to</span><span class="special">:</span>
<span class="number">1</span>
</pre>
<p>
where after initially expanding the macro to:
</p>
<pre class="programlisting"><span class="identifier">FMACRO3</span> <span class="identifier">FMACRO2</span><span class="special">()</span>
</pre>
<p>
VC++ erroneously rescans the sequence of preprocessing tokens more than once
rather than rescan just one more time for more macro names.
</p>
<p>
What these two particular preprocessor flaws in the VC++ compiler mean is
that although BOOST_VMD_IS_EMPTY does not fail with a compiler error in the
same case as with a standard C++ conforming compiler given previously, it
fails by giving the wrong result in another situation.
</p>
<p>
The failing situation is:
</p>
<p>
when the input to BOOST_VMD_IS_EMPTY resolves to only a function-like macro
name, and the function-like macro, when passed a single empty argument, expands
to a Boost PP tuple, BOOST_VMD_IS_EMPTY will erroneously return 1 when using
the Visual C++ compiler rather than either give a preprocessing error or
return 0.
</p>
<p>
Here is an example of the failure:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_empty</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">FMACRO4</span><span class="special">()</span> <span class="special">(</span> <span class="identifier">any_number_of_tuple_elements</span> <span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">FMACRO5</span><span class="special">(</span><span class="identifier">param</span><span class="special">)</span> <span class="special">(</span> <span class="identifier">any_number_of_tuple_elements</span> <span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">FMACRO6</span><span class="special">(</span><span class="identifier">param1</span><span class="special">,</span><span class="identifier">param2</span><span class="special">)</span> <span class="special">(</span> <span class="identifier">any_number_of_tuple_elements</span> <span class="special">)</span>
<span class="identifier">BOOST_VMD_IS_EMPTY</span><span class="special">(</span><span class="identifier">FMACRO4</span><span class="special">)</span> <span class="comment">// erroneously returns 1, instead of 0</span>
<span class="identifier">BOOST_VMD_IS_EMPTY</span><span class="special">(</span><span class="identifier">FMACRO5</span><span class="special">)</span> <span class="comment">// erroneously returns 1, instead of 0</span>
<span class="identifier">BOOST_VMD_IS_EMPTY</span><span class="special">(</span><span class="identifier">FMACRO6</span><span class="special">)</span> <span class="comment">// erroneously returns 1, instead of generating a preprocessing error</span>
</pre>
<p>
As with a standard C++ conforming compiler, we have a rare corner case where
the BOOST_VMD_IS_EMPTY will not work properly, but unfortunately in this
very similar but even rarer corner case with VC++, we will silently get an
incorrect result rather than a compiler error.
</p>
<p>
I want to reiterate that there is no perfect solution in C++ to the detection
of emptiness even for a C++ compiler whose preprocessor is completely conformant,
which VC++ obviously is not.
</p>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_test_empty.h6"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_test_empty.macro_flaw_conclusion"></a></span><a class="link" href="vmd_specific.html#variadic_macro_data.vmd_specific.vmd_test_empty.macro_flaw_conclusion">Macro
Flaw conclusion</a>
</h5>
<p>
With all of the above mentioned, the case(s) where BOOST_VMD_IS_EMPTY will
work incorrectly are very small, even with the erroneous VC++ preprocessor,
and I consider the macro worthwhile to use since it works correctly with
the vast majority of possible preprocessor input.
</p>
<p>
The case where it will not work, with both a C++ standard conforming preprocessor
or with Visual C++, occurs when the name of a function-like macro is part
of the input to BOOST_VMD_IS_EMPTY. Obviously the macro should be used by
the preprocessor metaprogrammer when the possible input to it is constrained
to eliminate the erroneous case.
</p>
<p>
Furthermore, since emptiness can correctly be tested for in nearly every
situation, the BOOST_VMD_IS_EMPTY macro can be used internally when the preprocessor
metaprogrammer wants to return data from a macro and all or part of that
data could be empty.
</p>
<p>
Therefore I believe the BOOST_VMD_IS_EMPTY macro is quite useful, despite
the corner case flaw which makes it imperfect. Consequently I believe that
the preprocessor metaprogrammer can use the concept of empty preprocessor
data in the design of his own macros.
</p>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_test_empty.h7"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_test_empty.using_the_macro"></a></span><a class="link" href="vmd_specific.html#variadic_macro_data.vmd_specific.vmd_test_empty.using_the_macro">Using
the macro</a>
</h5>
<p>
The macro BOOST_VMD_IS_EMPTY is used internally throughout VMD and macro
programmers may find this macro useful in their own programming efforts despite
the slight flaw in the way that it works.
</p>
<p>
You can use the general header file:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<p>
or you can use the individual header file:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_empty</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<p>
for the BOOST_VMD_IS_EMPTY macro.
</p>
</div>
<div class="footnotes">
<br><hr style="width:100; text-align:left;margin-left: 0">
<div id="ftn.variadic_macro_data.vmd_specific.vmd_test_empty.f0" class="footnote"><p><a href="#variadic_macro_data.vmd_specific.vmd_test_empty.f0" class="para"><sup class="para">[1] </sup></a>
For VC++ 8 the input is not variadic data but a single parameter
</p></div>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_data_types.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_specific/vmd_constraints.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,135 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Macro constraints</title>
<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../vmd_specific.html" title="Specific macros for working with data types">
<link rel="prev" href="../vmd_specific.html" title="Specific macros for working with data types">
<link rel="next" href="vmd_identifier.html" title="Identifiers">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../vmd_specific.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_specific.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_identifier.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="variadic_macro_data.vmd_specific.vmd_constraints"></a><a class="link" href="vmd_constraints.html" title="Macro constraints">Macro
constraints</a>
</h3></div></div></div>
<p>
When discussing the BOOST_VMD_IS_EMPTY macro I mentioned constraining input
to the macro. Now I will discuss what this means in terms of preprocessor
metaprogramming and input to macros in general.
</p>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_constraints.h0"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_constraints.constrained_input"></a></span><a class="link" href="vmd_constraints.html#variadic_macro_data.vmd_specific.vmd_constraints.constrained_input">Constrained
input</a>
</h5>
<p>
When a programmer designs any kinds of callables in C++ ( functions, member
functions etc. ), he specifies what the types of input and the return value
are. The C++ compiler enforces this specification at compile time. Similarly
at run-time a callable may check that its input falls within certain documented
and defined boundaries and react accordingly if it does not. This is all
part of the constraints for any callable in C++ and should be documented
by any good programmer.
</p>
<p>
The C++ preprocessor is much "dumber" than the C++ compiler and
even with the preprocessor metaprogramming constructs which Paul Mensonides
has created in Boost PP there is far less the preprocessor metaprogrammer
can do at preprocessing time to constrain argument input to a macro than
a programmer can do at compile-time and/or at run-time to constrain argument
input to a C++ callable. Nevertheless it is perfectly valid to document what
a macro expects as its argument input and, if a programmer does not follow
the constraint, the macro will fail to work properly. In the ideal case in
preprocessor metaprogramming the macro could tell whether or not the constraint
was met and could issue some sort of intelligible preprocessing error when
this occurred, but even within the reality of preprocessor metaprogramming
with Boost PP this is not always possible to do. Nevertheless if the user
of a macro does not follow the constraints for a macro parameter, as specified
in the documentation of a particular macro being invoked, any error which
occurs is the fault of that user. I realize that this may go against the
strongly held concept that programming errors must always be met with some
sort of compile-time or run-time occurrence which allows the programmer to
correct the error, rather than a silent failure which masks the error. Because
the preprocessor is "dumber" and cannot provide this occurrence
in all cases the error could unfortunately be masked, despite the fact that
the documentation specifies the correct input constraint(s). In the case
of the already discussed macro BOOST_VMD_IS_EMPTY, this masking of the error
could only occur with a preprocessor ( Visual C++ ) which is not C++ standard
conformant.
</p>
<p>
The Boost PP library does have a way of generating a preprocessing error,
without generating preprocessor output, but once again this way does not
work with the non-conformant preprocessor of Visual C++. The means to do
so using Boost PP is through the BOOST_PP_ASSERT macro. As will be seen and
discussed later VMD has an equivalent macro which will work with Visual C++
by producing incorrect C++ output rather than a preprocessing error, but
even this is not a complete solution since the incorrect C++ output produced
could be hidden.
</p>
<p>
Even the effort to produce a preprocessing error, or incorrect output inducing
a compile-time error, does not solve the problem of constrained input for
preprocessor metaprogramming. Often it is impossible to determine if the
input meets the constraints which the preprocessor metaprogrammer places
on it and documents. Certain preprocessing tokens cannot be checked reliably
for particular values, or a range of values, without the checking mechanism
itself creating a preprocessing error or undefined behavior.
</p>
<p>
This does not mean that one should give up attempting to check macro input
constraints. If it can be done I see the value of such checks and a number
of VMD macros, discussed later, are designed as preprocessing input constraint
checking macros. But the most important thing when dealing with macro input
constraints is that they should be carefully documented, and that the programmer
should know that if the constraints are not met either preprocessing errors
or incorrect macro results could be the results.
</p>
<p>
The VMD library, in order to present more preprocessor programming functionality
and flexibility, allows that erroneous results could occur if certain input
constraints are not met, whether the erroneous results are preprocessing
errors or incorrect output from a VMD macro. At the same time the VMD does
everything that the preprocessor is capable of doing to check the input constraints,
and carefully documents for each macro in the library what the input for
each could be in order to avoid erroneous output.
</p>
<p>
Documented macro input constraints are just as valid in the preprocessor
as compile-time/run-time constraints are valid in C++, even if the detection
of such constraints and/or the handling of constraints that are not met are
far more difficult, if not impossible, in the preprocessor than in the compile-time/run-time
processing of C++.
</p>
<p>
The VMD library uses constraints for most of it macros and the documentation
for those macros mentions the constraints that apply in order to use the
macro.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../vmd_specific.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_specific.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_identifier.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,262 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Identifiers</title>
<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../vmd_specific.html" title="Specific macros for working with data types">
<link rel="prev" href="vmd_constraints.html" title="Macro constraints">
<link rel="next" href="vmd_number.html" title="Numbers">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_constraints.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_specific.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_number.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="variadic_macro_data.vmd_specific.vmd_identifier"></a><a class="link" href="vmd_identifier.html" title="Identifiers">Identifiers</a>
</h3></div></div></div>
<p>
An identifier in VMD is either of two lower-level preprocessor possibilities:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
a preprocessing token 'identifier', which is essentially a sequence of
alphanumeric characters and the underscore character with the first character
not being a numeric character.
</li>
<li class="listitem">
a preprocessing token 'pp-number' that is an integral literal token.
</li>
</ul></div>
<p>
Here are some examples:
</p>
<pre class="programlisting"><span class="identifier">SOME_NAME</span>
<span class="identifier">_SOME_NAME</span>
<span class="identifier">SOME_123_NAME</span>
<span class="identifier">some_123_name</span>
<span class="identifier">sOMe_123_NAmE</span>
<span class="number">2367</span>
<span class="number">43e11</span>
<span class="number">0</span>
<span class="number">22</span>
<span class="number">654792</span>
<span class="number">0x1256</span>
</pre>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_identifier.h0"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_identifier.problem_testing_any_identifier"></a></span><a class="link" href="vmd_identifier.html#variadic_macro_data.vmd_specific.vmd_identifier.problem_testing_any_identifier">Problem
testing any identifier</a>
</h5>
<p>
One of the difficulties with identifiers in preprocessor metaprogramming
is safely testing for a particular one. VMD has a means of doing this within
a particular constraint for the characters that serve as the input.
</p>
<p>
The constraint is that the beginning input character, ignoring any whitespace,
passed as the input to test must be either:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
an identifier character, ie. an alphanumeric or an underscore
</li>
<li class="listitem">
the left parenthesis of a tuple
</li>
</ul></div>
<p>
and if the first character is not the left parenthesis of a tuple the remaining
characters must be alphanumeric or an underscore until a space character
or end of input occurs.
</p>
<p>
If this is not the case the behavior is undefined, and most likely a preprocessing
error will occur.
</p>
<p>
Given the input:
</p>
<pre class="programlisting"><span class="char">'s_anything'</span> <span class="special">:</span> <span class="identifier">can</span> <span class="identifier">be</span> <span class="identifier">tested</span>
<span class="char">'S_anything'</span> <span class="special">:</span> <span class="identifier">can</span> <span class="identifier">be</span> <span class="identifier">tested</span>
<span class="char">'s_anYthiNg'</span> <span class="special">:</span> <span class="identifier">can</span> <span class="identifier">be</span> <span class="identifier">tested</span>
<span class="char">'_anything'</span> <span class="special">:</span> <span class="identifier">can</span> <span class="identifier">be</span> <span class="identifier">tested</span>
<span class="char">'_Anything'</span> <span class="special">:</span> <span class="identifier">can</span> <span class="identifier">be</span> <span class="identifier">tested</span>
<span class="char">'_anytHIng'</span> <span class="special">:</span> <span class="identifier">can</span> <span class="identifier">be</span> <span class="identifier">tested</span>
<span class="char">'24'</span> <span class="special">:</span> <span class="identifier">can</span> <span class="identifier">be</span> <span class="identifier">tested</span>
<span class="char">'245e2'</span> <span class="special">:</span> <span class="identifier">can</span> <span class="identifier">be</span> <span class="identifier">tested</span>
<span class="char">'(anything)'</span> <span class="special">:</span> <span class="identifier">can</span> <span class="identifier">be</span> <span class="identifier">tested</span><span class="special">,</span> <span class="identifier">tuple</span>
<span class="char">'(anything) anything'</span> <span class="special">:</span> <span class="identifier">can</span> <span class="identifier">be</span> <span class="identifier">tested</span><span class="special">,</span> <span class="identifier">tuple</span> <span class="keyword">and</span> <span class="identifier">further</span> <span class="identifier">input</span>
<span class="char">'anything anything'</span> <span class="special">:</span> <span class="identifier">can</span> <span class="identifier">be</span> <span class="identifier">tested</span><span class="special">,</span> <span class="identifier">identifier</span> <span class="identifier">followed</span> <span class="identifier">by</span> <span class="identifier">space</span> <span class="identifier">character</span>
<span class="char">'%_anything'</span> <span class="special">:</span> <span class="identifier">undefined</span> <span class="identifier">behavior</span> <span class="keyword">and</span> <span class="identifier">most</span> <span class="identifier">likely</span> <span class="identifier">a</span> <span class="identifier">preprocessing</span> <span class="identifier">error</span> <span class="identifier">due</span> <span class="identifier">to</span> <span class="identifier">the</span> <span class="identifier">constraint</span>
<span class="char">'(_anything'</span> <span class="special">:</span> <span class="identifier">undefined</span> <span class="identifier">behavior</span> <span class="keyword">and</span> <span class="identifier">most</span> <span class="identifier">likely</span> <span class="identifier">a</span> <span class="identifier">preprocessing</span> <span class="identifier">error</span> <span class="identifier">due</span> <span class="identifier">to</span> <span class="identifier">the</span> <span class="identifier">constraint</span><span class="special">,</span> <span class="identifier">since</span> <span class="identifier">a</span> <span class="identifier">single</span> <span class="char">'('</span> <span class="identifier">does</span> <span class="keyword">not</span> <span class="identifier">form</span> <span class="identifier">a</span> <span class="identifier">tuple</span>
<span class="char">'44.3'</span> <span class="special">:</span> <span class="identifier">undefined</span> <span class="identifier">behavior</span> <span class="keyword">and</span> <span class="identifier">most</span> <span class="identifier">likely</span> <span class="identifier">a</span> <span class="identifier">preprocessing</span> <span class="identifier">error</span> <span class="identifier">due</span> <span class="identifier">to</span> <span class="identifier">the</span> <span class="identifier">constraint</span> <span class="identifier">since</span> <span class="char">'.'</span> <span class="identifier">is</span> <span class="keyword">not</span> <span class="identifier">alphanumeric</span>
</pre>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_identifier.h1"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_identifier.identifying_an_identifier"></a></span><a class="link" href="vmd_identifier.html#variadic_macro_data.vmd_specific.vmd_identifier.identifying_an_identifier">Identifying
an identifier</a>
</h5>
<p>
In VMD the only way an identifier can be identified in preprocessor input
is by a process called registration. In order to 'register' an identifier
to be recognized by VMD the end-user must create, for every identifier to
be recognized, an object-like macro whose form is:
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_identifier</span> <span class="special">(</span><span class="identifier">identifier</span><span class="special">)</span>
</pre>
<p>
where 'identifier' is a particular identifier we wish to identify. This is
called in VMD a registration macro.
</p>
<p>
It is recommended that such registration macros be created in a header file
which can be included before the end-user uses the identifier macros of VMD.
</p>
<p>
If a particular registration macro occurs more than once it is not a preprocessing
error, so duplicating a registration macro will not lead to any problems
since each registration macro of the same name will have the exact same object-like
macro expansion.
</p>
<p>
Within a given translation unit it could potentially happen that registration
macros have been included by header files which a particular end-user of
VMD has not created. This should also not lead to particular problems since
registration is a process for adding identifiers for any particular translation
unit. As we shall see VMD has macros for not only finding any identifier
in preprocessor input but for also finding any particular identifier in preprocessor
input.
</p>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_identifier.h2"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_identifier.testing_for_an_identifier_macro"></a></span><a class="link" href="vmd_identifier.html#variadic_macro_data.vmd_specific.vmd_identifier.testing_for_an_identifier_macro">Testing
for an identifier macro</a>
</h5>
<p>
The specific macro used to test for an identifier in VMD is called BOOST_VMD_IS_IDENTIFIER.
The macro takes one required parameter which is the input against which to
test.
</p>
<p>
When we invoke BOOST_VMD_IS_IDENTIFIER it returns 1 if the input represents
any registered identifier, otherwise it returns 0.
</p>
<p>
As an example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_identifier</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_yellow</span> <span class="special">(</span><span class="identifier">yellow</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_green</span> <span class="special">(</span><span class="identifier">green</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_blue</span> <span class="special">(</span><span class="identifier">blue</span><span class="special">)</span>
<span class="identifier">BOOST_VMD_IS_IDENTIFIER</span><span class="special">(</span><span class="identifier">some_input</span><span class="special">)</span> <span class="comment">// returns 1 if 'some_input' is 'yellow','green', or 'blue'</span>
<span class="identifier">BOOST_VMD_IS_IDENTIFIER</span><span class="special">(</span><span class="identifier">some_input</span><span class="special">)</span> <span class="comment">// returns 0 if 'some_input' is 'purple'</span>
</pre>
<p>
Essentially only registered identifiers can be found in VMD as identifiers.
</p>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_identifier.h3"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_identifier.detecting_a_particular_identifie"></a></span><a class="link" href="vmd_identifier.html#variadic_macro_data.vmd_specific.vmd_identifier.detecting_a_particular_identifie">Detecting
a particular identifier</a>
</h5>
<p>
Although registering an identifier allows VMD to recognize the string of
characters as a VMD identifier, the ability to detect a particular identifier
needs the end-user to define another macro:
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_identifier_identifier</span>
</pre>
<p>
where 'identifier' is a particular identifier we wish to detect. This object-like
macro expands to no output.
</p>
<p>
Like the registration macro multiple detection macros of the same identifier
in a translation unit does not cause a compiler problem since the exact same
object-like macro occurs.
</p>
<p>
The term for creating this macro is that we have potentially 'pre-detected'
the identifier and I will use the term pre-detected as the process of creating
the BOOST_VMD_DETECT macro.
</p>
<p>
The ability to detect that a VMD identifier is a particular identifier is
used in VMD macros when data is compared for equality/inequality as well
as when we want to match an identifier against a set of other identifiers.
These situations will be explained later in the documentation when the particular
macro functionality is discussed. If the programmer never uses the functionality
which these situations encompass there is no need to use pre-detection for
a registered identifier.
</p>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_identifier.h4"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_identifier.parsing_identifiers_and_undefine"></a></span><a class="link" href="vmd_identifier.html#variadic_macro_data.vmd_specific.vmd_identifier.parsing_identifiers_and_undefine">Parsing
identifiers and undefined behavior</a>
</h5>
<p>
The technique for parsing identifiers, once it is determined that the input
being parsed does not begin with a set of parentheses, uses preprocessor
concatenation in its parsing. This technique involves the preprocessor '##'
operator to concatenate input, and examine the results of that concatenation.
</p>
<p>
When preprocessor concatenation is used the result of the concatenation must
be a valid preprocessing token, else the behavior of the preprocessor is
undefined. In C++ 'undefined behavior' in general means that anything can
happen. In practical use when preprocessor concatenation does not produce
a valid preprocessing token, a compiler is most likely to generate a preprocessing
error. If the compiler chooses not to issue a preprocessing error the outcome
will always mean that parsing an identifier will fail. But because the outcome
is undefined behavior there is no absolute way that the programmer can determine
what the outcome will be when preprocessor concatenation is used and the
input being parsed contains preprocessor input which does not meet the constraints
for parsing an identifier mentioned at the beginning of this topic.
</p>
<p>
In this documentation I will be using the abbreviation 'UB' as the shortened
form of 'undefined behavior' to denote the particular occurrence where VMD
attempts to parse preprocessor input using preprocessor concatenation and
undefined behavior will occur.
</p>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_identifier.h5"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_identifier.usage"></a></span><a class="link" href="vmd_identifier.html#variadic_macro_data.vmd_specific.vmd_identifier.usage">Usage</a>
</h5>
<p>
To use the BOOST_VMD_IS_IDENTIFIER macro either include the general header:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<p>
or include the specific header:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_identifier</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_constraints.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_specific.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_number.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,135 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Identifying data types</title>
<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../vmd_specific.html" title="Specific macros for working with data types">
<link rel="prev" href="vmd_pp_data_types.html" title="VMD and Boost PP data types">
<link rel="next" href="../vmd_generic.html" title="Generic macros for working with data types">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_pp_data_types.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_specific.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../vmd_generic.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="variadic_macro_data.vmd_specific.vmd_identifying"></a><a class="link" href="vmd_identifying.html" title="Identifying data types">Identifying
data types</a>
</h3></div></div></div>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_identifying.h0"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_identifying.identifying_macros_and_boost_vmd"></a></span><a class="link" href="vmd_identifying.html#variadic_macro_data.vmd_specific.vmd_identifying.identifying_macros_and_boost_vmd">Identifying
macros and BOOST_VMD_IS_EMPTY </a>
</h5>
<p>
The various macros for identifying VMD data types complement the ability
to identify emptiness using BOOST_VMD_IS_EMPTY. The general name I will use
in this documentation for these specific macros is "identifying macros."
The identifying macros also share with BOOST_VMD_IS_EMPTY the inherent flaw
mentioned when discussing BOOST_VMD_IS_EMPTY, since they themselves use BOOST_VMD_IS_EMPTY
to determine that the input has ended.
</p>
<p>
To recapitulate the flaw with BOOST_VMD_IS_EMPTY:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
using a standard C++ compiler if the input ends with the name of a function-like
macro, and that macro takes two or more parameters, a preprocessing error
will occur.
</li>
<li class="listitem">
using the VC++ compiler if the input consists of the name of a function-like
macro, and that macro when invoked with no parameters returns a tuple,
the macro erroneously returns 1, meaning that the input is empty.
</li>
<li class="listitem">
even if the function-like macro takes one parameter, passing emptiness
to that macro could cause a preprocessing error.
</li>
</ul></div>
<p>
The obvious way to avoid the BOOST_VMD_IS_EMPTY problem with the identifying
macros is to design input so that the name of a function-like macro is never
passed as a parameter. This can be done, if one uses VMD and has situations
where the input could contain a function-like macro name, by having that
function-like macro name placed within a Boost PP data type, such as a tuple,
without attempting to identify the type of the tuple element using VMD. In
other word if the input is:
</p>
<pre class="programlisting"><span class="special">(</span> <span class="identifier">SOME_FUNCTION_MACRO_NAME</span> <span class="special">)</span>
</pre>
<p>
and we have the macro definition:
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">SOME_FUNCTION_MACRO_NAME</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier">y</span><span class="special">)</span> <span class="identifier">some_output</span>
</pre>
<p>
VMD can still parse the input as a tuple, if desired, using BOOST_VMD_IS_TUPLE
without encountering the BOOST_VMD_IS_EMPTY problem. However if the input
is:
</p>
<pre class="programlisting"><span class="identifier">SOME_FUNCTION_MACRO_NAME</span>
</pre>
<p>
either directly or through accessing the above tuple's first element, and
the programmer attempts to use BOOST_VMD_IS_IDENTIFIER with this input, the
BOOST_VMD_IS_EMPTY problem will occur.
</p>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_identifying.h1"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_identifying.identifying_macros_and_programmi"></a></span><a class="link" href="vmd_identifying.html#variadic_macro_data.vmd_specific.vmd_identifying.identifying_macros_and_programmi">Identifying
macros and programming flexibility </a>
</h5>
<p>
The VMD identifying macros give the preprocessor metaprogrammer a great amount
of flexibility when designing macros. It is not merely the flexibility of
allowing direct parameters to a macro to be different data types, and having
the macro work differently depending on the type of data passed to it, but
it is also the flexibility of allowing individual elements of the higher
level Boost PP data types to be different data types and have the macro work
correctly depending on the type of data type passed as part of those elements.
</p>
<p>
With this flexibility also comes a greater amount of responsibility. For
the macro designer this responsibility is twofold:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
To carefully document the possible combinations of acceptable data and
what they mean.
</li>
<li class="listitem">
To balance flexibility with ease of use so that the macro does not become
so hard to understand that the programmer invoking the macro gives up
using it entirely.
</li>
</ul></div>
<p>
For the programmer invoking a macro the responsibility is to understand the
documentation and not attempt to pass to the macro data which may cause incorrect
results or preprocessing errors.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_pp_data_types.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_specific.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../vmd_generic.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,154 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Numbers</title>
<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../vmd_specific.html" title="Specific macros for working with data types">
<link rel="prev" href="vmd_identifier.html" title="Identifiers">
<link rel="next" href="vmd_type.html" title="Types">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_identifier.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_specific.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_type.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="variadic_macro_data.vmd_specific.vmd_number"></a><a class="link" href="vmd_number.html" title="Numbers">Numbers</a>
</h3></div></div></div>
<p>
A number in VMD is a preprocessing 'pp-number', limited to a Boost PP number.
This is an integral literal between 0 and 256. The form of the number does
not contain leading zeros. Acceptable as numbers are:
</p>
<pre class="programlisting"><span class="number">0</span>
<span class="number">127</span>
<span class="number">33</span>
<span class="number">254</span>
<span class="number">18</span>
</pre>
<p>
but not:
</p>
<pre class="programlisting"><span class="number">033</span>
<span class="number">06</span>
<span class="number">00</span><span class="number">9</span>
<span class="number">00</span>
</pre>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_number.h0"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_number.problem_testing_any_number"></a></span><a class="link" href="vmd_number.html#variadic_macro_data.vmd_specific.vmd_number.problem_testing_any_number">Problem
testing any number</a>
</h5>
<p>
As can be seen from the explanation of an identifier, a number is merely
a small subset of all possible identifiers, for which VMD internally provides
registration macros for its use and pre-detection macros for its use. Therefore
the particular constraint on the input to test is exactly the same as for
identifiers.
</p>
<p>
The constraint is that the beginning input character, ignoring any whitespace,
passed as the input to test must be either:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
an identifier character, ie. an alphanumeric or an underscore
</li>
<li class="listitem">
the left parenthesis of a tuple
</li>
</ul></div>
<p>
and if the first character is not the left parenthesis of a tuple the remaining
characters must be alphanumeric or an underscore until a space character
or end of input occurs.
</p>
<p>
If this is not the case the behavior is undefined, and most likely a preprocessing
error will occur.
</p>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_number.h1"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_number.testing_for_a_number_macro"></a></span><a class="link" href="vmd_number.html#variadic_macro_data.vmd_specific.vmd_number.testing_for_a_number_macro">Testing
for a number macro</a>
</h5>
<p>
The macro used to test for any number in VMD is called BOOST_VMD_IS_NUMBER.
The macro takes a single parameter, the input to test against.
</p>
<p>
The macro returns 1 if the parameter is a Boost PP number, otherwise the
macro returns 0.
</p>
<p>
The Boost PP library has a great amount of functionality for working with
numbers, so once you use VMD to parse/test for a number you can use Boost
PP to work with that number in various ways. The VMD makes no attempt to
duplicate the functionality of numbers that in the Boost PP library.
</p>
<p>
Any number is also an identifier, which has been registered and pre-detected,
so you can also use the VMD functionality which works with identifiers to
work with a number as an identifier if you like.
</p>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_number.h2"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_number.example"></a></span><a class="link" href="vmd_number.html#variadic_macro_data.vmd_specific.vmd_number.example">Example</a>
</h5>
<p>
Let us look at an example of how to use BOOST_VMD_IS_NUMBER.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_number</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_VMD_IS_NUMBER</span><span class="special">(</span><span class="identifier">input</span><span class="special">)</span>
<span class="identifier">returns</span><span class="special">:</span>
<span class="keyword">if</span> <span class="identifier">input</span> <span class="special">=</span> <span class="number">0</span><span class="special">,</span> <span class="number">1</span>
<span class="keyword">if</span> <span class="identifier">input</span> <span class="special">=</span> <span class="number">44</span><span class="special">,</span> <span class="number">1</span>
<span class="keyword">if</span> <span class="identifier">input</span> <span class="special">=</span> <span class="identifier">SQUARE</span><span class="special">,</span> <span class="number">0</span>
<span class="keyword">if</span> <span class="identifier">input</span> <span class="special">=</span> <span class="number">44</span> <span class="identifier">DATA</span><span class="special">,</span> <span class="number">0</span> <span class="identifier">since</span> <span class="identifier">there</span> <span class="identifier">are</span> <span class="identifier">tokens</span> <span class="identifier">after</span> <span class="identifier">the</span> <span class="identifier">number</span>
<span class="keyword">if</span> <span class="identifier">input</span> <span class="special">=</span> <span class="number">044</span><span class="special">,</span> <span class="number">0</span> <span class="identifier">since</span> <span class="identifier">no</span> <span class="identifier">leading</span> <span class="identifier">zeros</span> <span class="identifier">are</span> <span class="identifier">allowed</span> <span class="keyword">for</span> <span class="identifier">our</span> <span class="identifier">Boost</span> <span class="identifier">PP</span> <span class="identifier">numbers</span>
<span class="keyword">if</span> <span class="identifier">input</span> <span class="special">=</span> <span class="number">256</span><span class="special">,</span> <span class="number">1</span>
<span class="keyword">if</span> <span class="identifier">input</span> <span class="special">=</span> <span class="number">257</span><span class="special">,</span> <span class="number">0</span> <span class="identifier">since</span> <span class="identifier">it</span> <span class="identifier">falls</span> <span class="identifier">outside</span> <span class="identifier">the</span> <span class="identifier">Boost</span> <span class="identifier">PP</span> <span class="identifier">number</span> <span class="identifier">range</span> <span class="identifier">of</span> <span class="number">0</span><span class="special">-</span><span class="number">256</span>
<span class="keyword">if</span> <span class="identifier">input</span> <span class="special">=</span> <span class="special">%</span><span class="number">44</span><span class="special">,</span> <span class="identifier">does</span> <span class="keyword">not</span> <span class="identifier">meet</span> <span class="identifier">the</span> <span class="identifier">constraint</span> <span class="identifier">therefore</span> <span class="identifier">undefined</span> <span class="identifier">behavior</span>
<span class="keyword">if</span> <span class="identifier">input</span> <span class="special">=</span> <span class="number">44.0</span><span class="special">,</span> <span class="identifier">does</span> <span class="keyword">not</span> <span class="identifier">meet</span> <span class="identifier">the</span> <span class="identifier">constraint</span> <span class="identifier">therefore</span> <span class="identifier">undefined</span> <span class="identifier">behavior</span>
<span class="keyword">if</span> <span class="identifier">input</span> <span class="special">=</span> <span class="special">(</span> <span class="number">44</span> <span class="special">),</span> <span class="number">0</span> <span class="identifier">since</span> <span class="identifier">the</span> <span class="identifier">macro</span> <span class="identifier">begins</span> <span class="identifier">with</span> <span class="identifier">a</span> <span class="identifier">tuple</span> <span class="keyword">and</span> <span class="keyword">this</span> <span class="identifier">can</span> <span class="identifier">be</span> <span class="identifier">tested</span> <span class="keyword">for</span>
</pre>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_number.h3"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_number.usage"></a></span><a class="link" href="vmd_number.html#variadic_macro_data.vmd_specific.vmd_number.usage">Usage</a>
</h5>
<p>
To use the BOOST_VMD_IS_NUMBER macro either include the general header:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<p>
or include the specific header:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_number</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_identifier.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_specific.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_type.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,379 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>VMD and Boost PP data types</title>
<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../vmd_specific.html" title="Specific macros for working with data types">
<link rel="prev" href="vmd_type.html" title="Types">
<link rel="next" href="vmd_identifying.html" title="Identifying data types">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_type.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_specific.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_identifying.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="variadic_macro_data.vmd_specific.vmd_pp_data_types"></a><a class="link" href="vmd_pp_data_types.html" title="VMD and Boost PP data types">VMD
and Boost PP data types</a>
</h3></div></div></div>
<p>
VMD is able to determine whether or not preprocessing input is a given Boost
PP data type. The VMD macros to do this are:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
BOOST_VMD_IS_ARRAY for an array
</li>
<li class="listitem">
BOOST_VMD_IS_LIST for a list
</li>
<li class="listitem">
BOOST_VMD_IS_SEQ for a seq
</li>
<li class="listitem">
BOOST_VMD_IS_TUPLE for a tuple
</li>
</ul></div>
<p>
Each of these macros take a single parameter as input and return 1 if the
parameter is the appropriate data type and 0 if it is not.
</p>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_pp_data_types.h0"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_pp_data_types.syntax_anomalies"></a></span><a class="link" href="vmd_pp_data_types.html#variadic_macro_data.vmd_specific.vmd_pp_data_types.syntax_anomalies">Syntax
anomalies</a>
</h5>
<p>
Both an array and a non-empty list are also a tuple. So if one has:
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">ANARRAY</span> <span class="special">(</span><span class="number">3</span><span class="special">,(</span><span class="identifier">a</span><span class="special">,</span><span class="identifier">b</span><span class="special">,</span><span class="identifier">c</span><span class="special">))</span>
<span class="preprocessor">#define</span> <span class="identifier">ALIST</span> <span class="special">(</span><span class="identifier">a</span><span class="special">,(</span><span class="identifier">b</span><span class="special">,(</span><span class="identifier">c</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">)))</span>
<span class="preprocessor">#define</span> <span class="identifier">ATUPLE</span> <span class="special">(</span><span class="identifier">a</span><span class="special">,</span><span class="identifier">b</span><span class="special">,</span><span class="identifier">c</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">ASEQ</span> <span class="special">(</span><span class="identifier">a</span><span class="special">)(</span><span class="identifier">b</span><span class="special">)(</span><span class="identifier">c</span><span class="special">)</span>
</pre>
<p>
then
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_tuple</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_VMD_IS_TUPLE</span><span class="special">(</span><span class="identifier">ANARRAY</span><span class="special">)</span> <span class="identifier">returns</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_IS_TUPLE</span><span class="special">(</span><span class="identifier">ALIST</span><span class="special">)</span> <span class="identifier">returns</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_IS_TUPLE</span><span class="special">(</span><span class="identifier">ATUPLE</span><span class="special">)</span> <span class="identifier">returns</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_IS_TUPLE</span><span class="special">(</span><span class="identifier">ASEQ</span><span class="special">)</span> <span class="identifier">returns</span> <span class="number">0</span>
</pre>
<p>
A list whose first element is the number 2 and whose second element is not
the end-of-list marker BOOST_PP_NIL is also an array. So if one has:
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">ALIST</span> <span class="special">(</span><span class="number">2</span><span class="special">,(</span><span class="number">3</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">))</span>
<span class="preprocessor">#define</span> <span class="identifier">ALIST2</span> <span class="special">(</span><span class="number">2</span><span class="special">,(</span><span class="number">3</span><span class="special">,(</span><span class="number">4</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">)))</span>
<span class="preprocessor">#define</span> <span class="identifier">ALIST3</span> <span class="special">(</span><span class="number">2</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">)</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_array</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_list</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_VMD_IS_LIST</span><span class="special">(</span><span class="identifier">ALIST</span><span class="special">)</span> <span class="identifier">returns</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_IS_LIST</span><span class="special">(</span><span class="identifier">ALIST2</span><span class="special">)</span> <span class="identifier">returns</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_IS_LIST</span><span class="special">(</span><span class="identifier">ALIST3</span><span class="special">)</span> <span class="identifier">returns</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_IS_ARRAY</span><span class="special">(</span><span class="identifier">ALIST</span><span class="special">)</span> <span class="identifier">returns</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_IS_ARRAY</span><span class="special">(</span><span class="identifier">ALIST2</span><span class="special">)</span> <span class="identifier">returns</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_IS_ARRAY</span><span class="special">(</span><span class="identifier">ALIST3</span><span class="special">)</span> <span class="identifier">returns</span> <span class="number">0</span>
</pre>
<p>
A single element tuple is also a one element seq. So if one has:
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">ASE_TUPLE</span> <span class="special">(</span><span class="identifier">a</span><span class="special">)</span>
</pre>
<p>
then
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_seq</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_tuple</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_VMD_IS_TUPLE</span><span class="special">(</span><span class="identifier">ASE_TUPLE</span><span class="special">)</span> <span class="identifier">returns</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_IS_SEQ</span><span class="special">(</span><span class="identifier">ASE_TUPLE</span><span class="special">)</span> <span class="identifier">returns</span> <span class="number">1</span>
</pre>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_pp_data_types.h1"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_pp_data_types.problem_when_testing_an_array"></a></span><a class="link" href="vmd_pp_data_types.html#variadic_macro_data.vmd_specific.vmd_pp_data_types.problem_when_testing_an_array">Problem
when testing an array</a>
</h5>
<p>
The form of an array is a two element tuple, where the first element is a
number and the second element is a tuple. The number specifies the size of
the tuple. Since when using variadic macros it is never necessary to specify
the size of a tuple, an array is largely obsolete. However VMD still supports
it.
</p>
<p>
The problem when testing for an array is that if the first element does not
obey the constraint on testing for a number, you will get UB.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_array</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_tuple</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">A_TUPLE</span> <span class="special">(&amp;</span><span class="identifier">anything</span><span class="special">,(</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">))</span>
<span class="identifier">BOOST_VMD_IS_ARRAY</span><span class="special">(</span><span class="identifier">A_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="identifier">give</span> <span class="identifier">UB</span> <span class="identifier">due</span> <span class="identifier">to</span> <span class="identifier">the</span> <span class="identifier">constraint</span>
<span class="identifier">BOOST_VMD_IS_TUPLE</span><span class="special">(</span><span class="identifier">A_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
</pre>
<p>
When VMD attempts to parse for an array, as it does when the BOOST_VMD_IS_ARRAY
is used, if first looks to see if the syntax represents a tuple with two
elements. Next it looks to see if the second element itself is a tuple. Finally
if it is satisfied that the previous checks are valid it tests whether the
first element is a number or not. It is in this final test, that the first
element is a valid number, where the UB could occur as explained in the topic
'Numbers'.
</p>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_pp_data_types.h2"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_pp_data_types.problem_when_testing_a_list"></a></span><a class="link" href="vmd_pp_data_types.html#variadic_macro_data.vmd_specific.vmd_pp_data_types.problem_when_testing_a_list">Problem
when testing a list</a>
</h5>
<p>
The form of a non-empty list is a two element tuple, where the first element
is the head of the list and can be anything and the second element is itself
a list or the end-of-list identifier BOOST_PP_NIL.
</p>
<p>
The problem when testing for a list is that if the second element does not
obey the constraint on testing for an identifier, since BOOST_PP_NIL is an
identifier and is tested as such, you will get UB.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_list</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_tuple</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">A_TUPLE</span> <span class="special">(</span><span class="identifier">element</span><span class="special">,&amp;</span><span class="identifier">anything</span><span class="special">)</span>
<span class="identifier">BOOST_VMD_IS_LIST</span><span class="special">(</span><span class="identifier">A_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="identifier">give</span> <span class="identifier">UB</span> <span class="identifier">due</span> <span class="identifier">to</span> <span class="identifier">the</span> <span class="identifier">constraint</span>
<span class="identifier">BOOST_VMD_IS_TUPLE</span><span class="special">(</span><span class="identifier">A_TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
</pre>
<p>
The form of an empty list is the identifier BOOST_PP_NIL. Therefore:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_identifier</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_list</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">A_BAD_EMPTY_LIST</span> <span class="special">&amp;</span><span class="identifier">BOOST_PP_NIL</span>
<span class="identifier">BOOST_VMD_IS_LIST</span><span class="special">(</span><span class="identifier">A_BAD_EMPTY_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="identifier">give</span> <span class="identifier">UB</span> <span class="identifier">due</span> <span class="identifier">to</span> <span class="identifier">the</span> <span class="identifier">constraint</span>
<span class="identifier">BOOST_VMD_IS_IDENTIFIER</span><span class="special">(</span><span class="identifier">A_BAD_EMPTY_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="identifier">give</span> <span class="identifier">UB</span> <span class="identifier">due</span> <span class="identifier">to</span> <span class="identifier">the</span> <span class="identifier">constraint</span>
</pre>
<p>
When VMD attempts to parse for a list, as it does when the BOOST_VMD_IS_LIST
is used, if first looks to see if the syntax represents a tuple with two
elements. If it is not a tuple with two elements it will check for the end-of-list.
If it is a tuple with two elements it looks to see if the second element
is a list. In both these paths it must always eventually check for the end-of-list
notation BOOST_PP_NIL, which is an identifier in VMD. It is in this final
test, that the end-of-list notation exists as a VMD identifier, where the
UB could occur as explained in the topic 'Identifiers'.
</p>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_pp_data_types.h3"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_pp_data_types.distinguishing_a_seq_and_a_tuple"></a></span><a class="link" href="vmd_pp_data_types.html#variadic_macro_data.vmd_specific.vmd_pp_data_types.distinguishing_a_seq_and_a_tuple">Distinguishing
a seq and a tuple</a>
</h5>
<p>
As has previously been mentioned a single element tuple is also a one element
seq.
</p>
<p>
However, as will be discussed later in the documentation, when VMD has to
determine the type of such data, it always returns it as a tuple ( BOOST_VMD_TYPE_TUPLE
).
</p>
<p>
If our data consists of more than one consecutive tuple of a single element
the data is a seq:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_seq</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_tuple</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">ST_DATA</span> <span class="special">(</span><span class="identifier">somedata</span><span class="special">)(</span><span class="identifier">some_other_data</span><span class="special">)</span>
<span class="identifier">BOOST_VMD_IS_SEQ</span><span class="special">(</span><span class="identifier">ST_DATA</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_IS_TUPLE</span><span class="special">(</span><span class="identifier">ST_DATA</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span>
</pre>
<p>
However if the data consists of a mixture we need to distinguish how VMD
parses the data. The rule is that VMD always parses a single element tuple
as a tuple unless it is followed by one or more single element tuples, in
which case it is a seq.
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">ST_DATA</span> <span class="special">(</span><span class="identifier">somedata</span><span class="special">)(</span><span class="identifier">element1</span><span class="special">,</span><span class="identifier">element2</span><span class="special">)</span>
</pre>
<p>
VMD parses the above data as 2 consecutive tuples. The first tuple is the
single element tuple '(somedata)' and the second tuple is the multi element
tuple '(element1,element2)'.
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">ST_DATA</span> <span class="special">(</span><span class="identifier">element1</span><span class="special">,</span><span class="identifier">element2</span><span class="special">)(</span><span class="identifier">somedata</span><span class="special">)</span>
</pre>
<p>
VMD parses the above data as 2 consecutive tuples. The first tuple is the
multi element tuple '(element1,element2)' and the second tuple is the single
element tuple '(somedata)'.
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">ST_DATA</span> <span class="special">(</span><span class="identifier">somedata</span><span class="special">)(</span><span class="identifier">some_other_data</span><span class="special">)(</span><span class="identifier">element1</span><span class="special">,</span><span class="identifier">element2</span><span class="special">)</span>
</pre>
<p>
VMD parses the above data as a seq followed by a tuple. The seq is '(somedata)(some_other_data)'
and the tuple is '(element1,element2)'.
</p>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_pp_data_types.h4"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_pp_data_types.empty_boost_pp_data_types"></a></span><a class="link" href="vmd_pp_data_types.html#variadic_macro_data.vmd_specific.vmd_pp_data_types.empty_boost_pp_data_types">Empty
Boost PP data types</a>
</h5>
<p>
An array and a list can be empty.
</p>
<p>
An empty array has the form '(0,())', and is a perfectly valid array.
</p>
<p>
You can test for an empty array using the macro BOOST_VMD_IS_EMPTY_ARRAY.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_array</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_empty_array</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">AN_ARRAY</span> <span class="special">(</span><span class="number">1</span><span class="special">,(</span><span class="number">1</span><span class="special">))</span>
<span class="preprocessor">#define</span> <span class="identifier">AN_EMPTY_ARRAY</span> <span class="special">(</span><span class="number">0</span><span class="special">,())</span>
<span class="identifier">BOOST_VMD_IS_ARRAY</span><span class="special">(</span><span class="identifier">AN_ARRAY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_IS_ARRAY</span><span class="special">(</span><span class="identifier">AN_EMPTY_ARRAY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_IS_EMPTY_ARRAY</span><span class="special">(</span><span class="identifier">AN_EMPTY_ARRAY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_IS_EMPTY_ARRAY</span><span class="special">()</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span>
<span class="identifier">BOOST_VMD_IS_EMPTY_ARRAY</span><span class="special">(</span><span class="identifier">AN_ARRAY</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span>
</pre>
<p>
An empty list has the form 'BOOST_PP_NIL', and is a perfectly valid list.
</p>
<p>
You can test for an empty list using the macro BOOST_VMD_IS_EMPTY_LIST.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_empty_list</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_list</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">A_LIST</span> <span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">BOOST_PP_NIL</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">AN_EMPTY_LIST</span> <span class="identifier">BOOST_PP_NIL</span>
<span class="identifier">BOOST_VMD_IS_LIST</span><span class="special">(</span><span class="identifier">A_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_IS_LIST</span><span class="special">(</span><span class="identifier">AN_EMPTY_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_IS_EMPTY_LIST</span><span class="special">(</span><span class="identifier">AN_EMPTY_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_IS_EMPTY_LIST</span><span class="special">()</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span>
<span class="identifier">BOOST_VMD_IS_EMPTY_LIST</span><span class="special">(</span><span class="identifier">A_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span>
</pre>
<p>
Neither seqs or tuples can be empty when using Boost PP. Because of this
if you convert from an empty array or list to a seq or tuple using Boost
PP macros to do so you will get undefined behavior.
</p>
<p>
The syntax '()', which is called an empty parenthesis, is neither a zero-element
seq or a tuple consisting of no elements. Rather it is either a one-element
seq whose content is emptiness or a single-element tuple whose content is
emptiness.
</p>
<p>
VMD supports the syntax of an empty parenthesis. You can test for it using
the macro BOOST_VMD_IS_PARENS_EMPTY.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_parens_empty</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_seq</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_tuple</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">EMPTY_PARENS</span> <span class="special">()</span>
<span class="preprocessor">#define</span> <span class="identifier">TUPLE</span> <span class="special">(</span><span class="number">0</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">SEQ</span> <span class="special">(</span><span class="number">0</span><span class="special">)(</span><span class="number">1</span><span class="special">)</span>
<span class="identifier">BOOST_VMD_IS_TUPLE</span><span class="special">(</span><span class="identifier">EMPTY_PARENS</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_IS_SEQ</span><span class="special">(</span><span class="identifier">EMPTY_PARENS</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_IS_PARENS_EMPTY</span><span class="special">(</span><span class="identifier">EMPTY_PARENS</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">1</span>
<span class="identifier">BOOST_VMD_IS_PARENS_EMPTY</span><span class="special">()</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span>
<span class="identifier">BOOST_VMD_IS_PARENS_EMPTY</span><span class="special">(</span><span class="identifier">TUPLE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span>
<span class="identifier">BOOST_VMD_IS_PARENS_EMPTY</span><span class="special">(</span><span class="identifier">SEQ</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="number">0</span>
</pre>
<p>
The VC++8 compiler ( Visual Studio 2005 ), which is the oldest VC++ version
which VMD supports, has trouble working with the empty parenthesis syntax.
Therefore if you have to use VC++8 avoid its use, otherwise you should be
fine using it if you desire.
</p>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_pp_data_types.h5"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_pp_data_types.using_a_tuple_instead_of_an_arra"></a></span><a class="link" href="vmd_pp_data_types.html#variadic_macro_data.vmd_specific.vmd_pp_data_types.using_a_tuple_instead_of_an_arra">Using
a tuple instead of an array</a>
</h5>
<p>
When using variadic macros, the fact that an array can be empty is its only
advantage over a tuple. Otherwise using a tuple is always easier since the
syntax is simpler; you never have to notate the tuple's size.
</p>
<p>
Since VMD fully supports passing and returning emptiness you could use a
tuple instead of an array in all situations and simply pass or return emptiness
to represent an "empty" tuple, and as an equivalent to an empty
array.
</p>
<p>
This notion of using emptiness to represent an "empty" tuple can
also be extended to using emptiness to represent an "empty" seq.
However functionality in Boost PP will not recognize emptiness as an empty
tuple or seq, nor can you work with emptiness to represent an empty tuple
or empty seq using the Boost PP functionality for a tuple or a seq. For a
solution to using emptiness to represent an "empty" tuple or an
"empty" seq VMD has functionality which will be explained when
we look at our last area of functionality in VMD, useful variadic macros
not in Boost PP.
</p>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_pp_data_types.h6"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_pp_data_types.usage"></a></span><a class="link" href="vmd_pp_data_types.html#variadic_macro_data.vmd_specific.vmd_pp_data_types.usage">Usage</a>
</h5>
<p>
You can use the general header file:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<p>
or you can use individual header files for each of these macros. The individual
header files are:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_array</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// for the BOOST_VMD_IS_ARRAY macro</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_list</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// for the BOOST_VMD_IS_LIST macro</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_seq</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// for the BOOST_VMD_IS_SEQ macro</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_tuple</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// for the BOOST_VMD_IS_TUPLE macro.</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_empty_array</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// for the BOOST_VMD_IS_EMPTY_ARRAY macro.</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_empty_list</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// for the BOOST_VMD_IS_EMPTY_LIST macro.</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_parens_empty</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// for the BOOST_VMD_IS_PARENS_EMPTY macro.</span>
</pre>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_type.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_specific.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_identifying.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,153 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Types</title>
<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../vmd_specific.html" title="Specific macros for working with data types">
<link rel="prev" href="vmd_number.html" title="Numbers">
<link rel="next" href="vmd_pp_data_types.html" title="VMD and Boost PP data types">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_number.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_specific.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_pp_data_types.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="variadic_macro_data.vmd_specific.vmd_type"></a><a class="link" href="vmd_type.html" title="Types">Types</a>
</h3></div></div></div>
<p>
A subset of identifiers is VMD types, called a 'v-type'. These are identifiers
which represent all of the preprocessor data types which VMD can parse. This
subset of identifiers is automatically registered and pre-detected by VMD.
Each identifier type begins with the unique prefix 'BOOST_VMD_TYPE_'.
</p>
<p>
The actual types are:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
BOOST_VMD_TYPE_EMPTY, represents emptiness, ie. "empty data"
</li>
<li class="listitem">
BOOST_VMD_TYPE_ARRAY, a Boost PP array
</li>
<li class="listitem">
BOOST_VMD_TYPE_LIST, a Boost PP list
</li>
<li class="listitem">
BOOST_VMD_TYPE_SEQ, a Boost PP seq
</li>
<li class="listitem">
BOOST_VMD_TYPE_TUPLE, a Boost PP tuple
</li>
<li class="listitem">
BOOST_VMD_TYPE_IDENTIFIER, identifier
</li>
<li class="listitem">
BOOST_BMD_TYPE_NUMBER, a number
</li>
<li class="listitem">
BOOST_VMD_TYPE_TYPE, a type itself
</li>
<li class="listitem">
BOOST_VMD_TYPE_SEQUENCE, a sequence
</li>
<li class="listitem">
BOOST_VMD_TYPE_UNKNOWN, an unknown type
</li>
</ul></div>
<p>
Since a v-type is itself an identifier the particular constraint on the input
to test is exactly the same as for identifiers.
</p>
<p>
The constraint is that the beginning input character, ignoring any whitespace,
passed as the input to test must be either:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
an identifier character, ie. an alphanumeric or an underscore
</li>
<li class="listitem">
the left parenthesis of a tuple
</li>
</ul></div>
<p>
and if the first character is not the left parenthesis of a tuple the remaining
characters must be alphanumeric or an underscore until a space character
or end of input occurs.
</p>
<p>
If this is not the case the behavior is undefined, and most likely a preprocessing
error will occur.
</p>
<p>
The macro used to test for a particular type in VMD is called BOOST_VMD_IS_TYPE.
The macro takes a single parameter, the input to test against.
</p>
<p>
The macro returns 1 if the parameter is a v-type, otherwise the macro returns
0.
</p>
<p>
A v-type is also an identifier, which has been registered and pre-detected,
so you can also use the VMD functionality which works with identifiers to
work with a v-type as an identifier if you like.
</p>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_type.h0"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_type.example"></a></span><a class="link" href="vmd_type.html#variadic_macro_data.vmd_specific.vmd_type.example">Example</a>
</h5>
<p>
Let us look at an example of how to use BOOST_VMD_IS_TYPE.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_type</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_VMD_IS_TYPE</span><span class="special">(</span><span class="identifier">input</span><span class="special">)</span>
<span class="identifier">returns</span><span class="special">:</span>
<span class="keyword">if</span> <span class="identifier">input</span> <span class="special">=</span> <span class="identifier">BOOST_VMD_TYPE_SEQ</span><span class="special">,</span> <span class="number">1</span>
<span class="keyword">if</span> <span class="identifier">input</span> <span class="special">=</span> <span class="identifier">BOOST_VMD_TYPE_NUMBER</span><span class="special">,</span> <span class="number">1</span>
<span class="keyword">if</span> <span class="identifier">input</span> <span class="special">=</span> <span class="identifier">SQUARE</span><span class="special">,</span> <span class="number">0</span>
<span class="keyword">if</span> <span class="identifier">input</span> <span class="special">=</span> <span class="identifier">BOOST_VMD_TYPE_IDENTIFIER</span> <span class="identifier">DATA</span><span class="special">,</span> <span class="number">0</span> <span class="identifier">since</span> <span class="identifier">there</span> <span class="identifier">are</span> <span class="identifier">tokens</span> <span class="identifier">after</span> <span class="identifier">the</span> <span class="identifier">type</span>
<span class="keyword">if</span> <span class="identifier">input</span> <span class="special">=</span> <span class="special">%</span><span class="number">44</span><span class="special">,</span> <span class="identifier">does</span> <span class="keyword">not</span> <span class="identifier">meet</span> <span class="identifier">the</span> <span class="identifier">constraint</span> <span class="identifier">therefore</span> <span class="identifier">undefined</span> <span class="identifier">behavior</span>
<span class="keyword">if</span> <span class="identifier">input</span> <span class="special">=</span> <span class="special">(</span> <span class="identifier">BOOST_VMD_TYPE_EMPTY</span> <span class="special">),</span> <span class="number">0</span> <span class="identifier">since</span> <span class="identifier">the</span> <span class="identifier">macro</span> <span class="identifier">begins</span> <span class="identifier">with</span> <span class="identifier">a</span> <span class="identifier">tuple</span> <span class="keyword">and</span> <span class="keyword">this</span> <span class="identifier">can</span> <span class="identifier">be</span> <span class="identifier">tested</span> <span class="keyword">for</span>
</pre>
<h5>
<a name="variadic_macro_data.vmd_specific.vmd_type.h1"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_type.usage"></a></span><a class="link" href="vmd_type.html#variadic_macro_data.vmd_specific.vmd_type.usage">Usage</a>
</h5>
<p>
To use the BOOST_VMD_IS_TYPE macro either include the general header:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<p>
or include the specific header:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_type</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_number.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_specific.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_pp_data_types.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,266 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Useful variadic macros not in Boost PP</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="prev" href="vmd_identifier_subtype.html" title="Identifier subtypes">
<link rel="next" href="vmd_useful/vmd_identity.html" title="Generating emptiness and identity">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_identifier_subtype.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_useful/vmd_identity.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="variadic_macro_data.vmd_useful"></a><a class="link" href="vmd_useful.html" title="Useful variadic macros not in Boost PP">Useful variadic macros
not in Boost PP</a>
</h2></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="vmd_useful.html#variadic_macro_data.vmd_useful.vmd_assert">Asserting
and data types</a></span></dt>
<dt><span class="section"><a href="vmd_useful/vmd_identity.html">Generating
emptiness and identity</a></span></dt>
<dt><span class="section"><a href="vmd_useful/vmd_empty_ppdata.html">Functionality
for "empty" seqs and tuples</a></span></dt>
</dl></div>
<p>
Previous sections of this documentation have explained how VMD can be used
to parse VMD data types, as well as recognize emptiness.
</p>
<p>
Another area of functionality of VMD involves useful variadic macros, based
on the previous functionality, which expands on similar macros already in Boost
PP. These variadic macros can be divided into sections illustrating these areas
of behavior:
</p>
<div class="orderedlist"><ol class="orderedlist" type="1">
<li class="listitem">
Expanded assertion macros
</li>
<li class="listitem">
Expanded identity functionality
</li>
<li class="listitem">
Expanded seq and tuple functionality for "empty" seqs and tuples
</li>
</ol></div>
<p>
Sub-sections for each of these now follow in the documentation.
</p>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="variadic_macro_data.vmd_useful.vmd_assert"></a><a class="link" href="vmd_useful.html#variadic_macro_data.vmd_useful.vmd_assert" title="Asserting and data types">Asserting
and data types</a>
</h3></div></div></div>
<p>
The VMD macros for identifying data types work best when the macro logic
can take different paths depending on the type of data being passed for a
macro parameter. But occasionally the preprocessor metaprogrammer wants to
simply verify that the macro parameter data is of the correct data type,
else a preprocessing error should be generated to notify the programmer invoking
the macro that the data passed is the incorrect type.
</p>
<h5>
<a name="variadic_macro_data.vmd_useful.vmd_assert.h0"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_useful.vmd_assert.using_boost_vmd_assert"></a></span><a class="link" href="vmd_useful.html#variadic_macro_data.vmd_useful.vmd_assert.using_boost_vmd_assert">Using
BOOST_VMD_ASSERT</a>
</h5>
<p>
The Boost PP library has a macro which produces a preprocessing error when
the condition passed to it is 0. This macro is called BOOST_PP_ASSERT. The
macro produces a preprocessor error by forcing a call to an internal macro
with the wrong number of arguments. According to the C++ standard this should
always cause an immediate preprocessing error for conforming compilers.
</p>
<p>
Unfortunately VC++ will only produce a warning when the wrong number of arguments
are passed to a macro. Therefore the BOOST_PP_ASSERT macro does not produce
a preprocessing error using VC++. Amazingly enough there appears to be no
other way in which VC++ can be forced to issue a preprocessing error by invoking
a macro ( if you find one please tell me about it ). However one can create
invalid C++ as the output from a macro invocation which causes VC++ to produce
a compiler error when the VC++ compiler later encounters the construct.
</p>
<p>
This is what the macro BOOST_VMD_ASSERT does. It takes the same conditional
argument as BOOST_PP_ASSERT and it calls BOOST_PP_ASSERT when not used with
VC++, otherwise if the condition is 0 it generates a compiler error by generating
invalid C++ when used with VC++. The compiler error is generated by producing
invalid C++ whose form is:
</p>
<pre class="programlisting"><span class="keyword">typedef</span> <span class="keyword">char</span> <span class="identifier">BOOST_VMD_ASSERT_ERROR</span><span class="special">[-</span><span class="number">1</span><span class="special">];</span>
</pre>
<p>
By passing a second optional argument, whose form is a preprocessing identifier,
to BOOST_VMD_ASSERT you can generate the invalid C++ for VC++, if the first
argument is 0, of the form:
</p>
<pre class="programlisting"><span class="keyword">typedef</span> <span class="keyword">char</span> <span class="identifier">optional_argument</span><span class="special">[-</span><span class="number">1</span><span class="special">];</span>
</pre>
<p>
instead. This may give a little more clarity, if desired, to the C++ error
generated.
</p>
<p>
If the first conditional argument is not 0, BOOST_VMD_ASSERT produces no
output.
</p>
<h5>
<a name="variadic_macro_data.vmd_useful.vmd_assert.h1"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_useful.vmd_assert.boost_vmd_assert_usage"></a></span><a class="link" href="vmd_useful.html#variadic_macro_data.vmd_useful.vmd_assert.boost_vmd_assert_usage">BOOST_VMD_ASSERT
Usage</a>
</h5>
<p>
To use the BOOST_VMD_ASSERT macro either include the general header:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<p>
or include the specific header:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">assert</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<h5>
<a name="variadic_macro_data.vmd_useful.vmd_assert.h2"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_useful.vmd_assert.assertions_for_data_types"></a></span><a class="link" href="vmd_useful.html#variadic_macro_data.vmd_useful.vmd_assert.assertions_for_data_types">Assertions
for data types </a>
</h5>
<p>
The data types have their own assertion macros. These are largely just shortcuts
for passing the result of the identifying macros to BOOST_VMD_ASSERT. These
assertion macros are:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
emptiness, BOOST_VMD_ASSERT_IS_EMPTY
</li>
<li class="listitem">
identifier, BOOST_VMD_ASSERT_IS_IDENTIFIER
</li>
<li class="listitem">
number, BOOST_VMD_ASSERT_IS_NUMBER
</li>
<li class="listitem">
array, BOOST_VMD_ASSERT_IS_ARRAY
</li>
<li class="listitem">
list, BOOST_VMD_ASSERT_IS_LIST
</li>
<li class="listitem">
seq, BOOST_VMD_ASSERT_IS_SEQ
</li>
<li class="listitem">
tuple, BOOST_VMD_ASSERT_IS_TUPLE
</li>
<li class="listitem">
type, BOOST_VMD_ASSERT_IS_TYPE
</li>
</ul></div>
<p>
Each of these macros take as parameters the exact same argument as their
corresponding identifying macros. But instead of returning non-zero or 0,
each of these macros produce a compiler error if the type of the input is
not correct.
</p>
<p>
Each of these macros only check for its assertion when the macro BOOST_VMD_ASSERT_DATA
is set to 1. By default BOOST_VMD_ASSERT_DATA is only set to 1 in compiler
debug mode. The programmer can manually set BOOST_VMD_ASSERT_DATA to 1 prior
to using one the data types assert macros if he wishes.
</p>
<h5>
<a name="variadic_macro_data.vmd_useful.vmd_assert.h3"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_useful.vmd_assert.boost_vmd_assert_usage0"></a></span><a class="link" href="vmd_useful.html#variadic_macro_data.vmd_useful.vmd_assert.boost_vmd_assert_usage0">BOOST_VMD_ASSERT_...
Usage</a>
</h5>
<p>
To use the individual BOOST_VMD_ASSERT_... macros either include the general
header:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<p>
or include the specific header:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">assert_is_empty</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// BOOST_VMD_ASSERT_IS_EMPTY</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">assert_is_identifier</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// BOOST_VMD_ASSERT_IS_IDENTIFIER</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">assert_is_number</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// BOOST_VMD_ASSERT_IS_NUMBER</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">assert_is_array</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// BOOST_VMD_ASSERT_IS_ARRAY</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">assert_is_list</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// BOOST_VMD_ASSERT_IS_LIST</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">assert_is_seq</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// BOOST_VMD_ASSERT_IS_SEQ</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">assert_is_tuple</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// BOOST_VMD_ASSERT_IS_TUPLE</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">assert_is_type</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// BOOST_VMD_ASSERT_IS_TYPE</span>
</pre>
<h5>
<a name="variadic_macro_data.vmd_useful.vmd_assert.h4"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_useful.vmd_assert.assertions_and_vc"></a></span><a class="link" href="vmd_useful.html#variadic_macro_data.vmd_useful.vmd_assert.assertions_and_vc">Assertions
and VC++ </a>
</h5>
<p>
The VC++ compiler has a quirk when dealing with BOOST_VMD_ASSERT and the
data type assert macros. If you invoke one of the assert macros within another
macro which would normally generate output preprocessor tokens, it is necessary
when using VC++ to concatenate the result of the assert macro to whatever
other preprocessor data is being generated, even if the assert macro does
not generate an error.
</p>
<p>
As a simple example let us suppose we have a macro expecting a tuple and
generating 1 if the tuple has more than 2 elements, otherwise it generates
0. Ordinarily we could write:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">comparison</span><span class="special">/</span><span class="identifier">greater</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">control</span><span class="special">/</span><span class="identifier">iif</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">tuple</span><span class="special">/</span><span class="identifier">size</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">assert_is_tuple</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">AMACRO</span><span class="special">(</span><span class="identifier">atuple</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_ASSERT_IS_TUPLE</span><span class="special">(</span><span class="identifier">atuple</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_IIF</span><span class="special">(</span><span class="identifier">BOOST_PP_GREATER</span><span class="special">(</span><span class="identifier">BOOST_PP_TUPLE_SIZE</span><span class="special">(</span><span class="identifier">atuple</span><span class="special">),</span> <span class="number">2</span><span class="special">),</span><span class="number">1</span><span class="special">,</span><span class="number">0</span><span class="special">)</span>
</pre>
<p>
but for VC++ we must write
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">cat</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">comparison</span><span class="special">/</span><span class="identifier">greater</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">control</span><span class="special">/</span><span class="identifier">iif</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">tuple</span><span class="special">/</span><span class="identifier">size</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">assert_is_tuple</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">AMACRO</span><span class="special">(</span><span class="identifier">atuple</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_CAT</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_ASSERT_IS_TUPLE</span><span class="special">(</span><span class="identifier">atuple</span><span class="special">),</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_IIF</span><span class="special">(</span><span class="identifier">BOOST_PP_GREATER</span><span class="special">(</span><span class="identifier">BOOST_PP_TUPLE_SIZE</span><span class="special">(</span><span class="identifier">atuple</span><span class="special">),</span> <span class="number">2</span><span class="special">),</span><span class="number">1</span><span class="special">,</span><span class="number">0</span><span class="special">)</span> <span class="special">\</span>
<span class="special">)</span>
</pre>
<p>
VC++ does not work correctly in the first instance, erroneously getting confused
as far as compiler output is concerned. But by using BOOST_PP_CAT in the
second condition VC++ will work correctly with VMD assertions.
</p>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_identifier_subtype.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_useful/vmd_identity.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,313 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Generating emptiness and identity</title>
<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../vmd_useful.html" title="Useful variadic macros not in Boost PP">
<link rel="prev" href="../vmd_useful.html" title="Useful variadic macros not in Boost PP">
<link rel="next" href="vmd_empty_ppdata.html" title='Functionality for "empty" seqs and tuples'>
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../vmd_useful.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_useful.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_empty_ppdata.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="variadic_macro_data.vmd_useful.vmd_identity"></a><a class="link" href="vmd_identity.html" title="Generating emptiness and identity">Generating
emptiness and identity</a>
</h3></div></div></div>
<h5>
<a name="variadic_macro_data.vmd_useful.vmd_identity.h0"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_useful.vmd_identity.using_boost_pp_empty_and_boost_p"></a></span><a class="link" href="vmd_identity.html#variadic_macro_data.vmd_useful.vmd_identity.using_boost_pp_empty_and_boost_p">Using
BOOST_PP_EMPTY and BOOST_PP_IDENTITY</a>
</h5>
<p>
Boost PP Has a macro called BOOST_PP_EMPTY() which expands to nothing.
</p>
<p>
Ordinarily this would not seem that useful, but the macro can be used in
situations where one wants to return a specific value even though a further
macro call syntax is required taking no parameters. This sort of usefulness
occurs in Boost PP when there are two paths to take depending on the outcome
of a BOOST_PP_IF or BOOST_PP_IIF logic. Here is an artificial example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">control</span><span class="special">/</span><span class="identifier">iif</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">facilities</span><span class="special">/</span><span class="identifier">empty</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">MACRO_CHOICE</span><span class="special">(</span><span class="identifier">parameter</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_IIF</span><span class="special">(</span><span class="identifier">parameter</span><span class="special">)</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">MACRO_CALL_IF_PARAMETER_1</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">SOME_FIXED_VALUE</span> <span class="identifier">BOOST_PP_EMPTY</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">()</span>
<span class="preprocessor">#define</span> <span class="identifier">MACRO_CALL_IF_PARAMETER_1</span><span class="special">()</span> <span class="identifier">some_processing</span>
</pre>
<p>
In the general logic above is: if parameter is 1 another macro is invoked,
whereas if the parameter is 0 some fixed value is returned. The reason that
this is useful is that one may not want to code the MACRO_CHOICE macro in
this way:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">control</span><span class="special">/</span><span class="identifier">iif</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">MACRO_CHOICE</span><span class="special">(</span><span class="identifier">parameter</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_IIF</span><span class="special">(</span><span class="identifier">parameter</span><span class="special">)</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">MACRO_CALL_IF_PARAMETER_1</span><span class="special">(),</span> <span class="special">\</span>
<span class="identifier">SOME_FIXED_VALUE</span> <span class="special">\</span>
<span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">MACRO_CALL_IF_PARAMETER_1</span><span class="special">()</span> <span class="identifier">some_processing</span>
</pre>
<p>
because it is inefficient. The invocation of MACRO_CALL_IF_PARAMETER_1 will
still be generated even when 'parameter' is 0.
</p>
<p>
This idiom of returning a fixed value through the use of BOOST_PP_EMPTY is
so useful that Boost PP has an accompanying macro to BOOST_PP_EMPTY to work
with it. This accompanying macro is BOOST_PP_IDENTITY(value)(). Essentially
BOOST_PP_IDENTITY returns its value when it is invoked. Again, like BOOST_PP_EMPTY,
the final invocation must be done with no value.
</p>
<p>
Our example from above, which originally used BOOST_PP_EMPTY to return a
fixed value, is now:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">control</span><span class="special">/</span><span class="identifier">iif</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">facilities</span><span class="special">/</span><span class="identifier">identity</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">MACRO_CHOICE</span><span class="special">(</span><span class="identifier">parameter</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_IIF</span><span class="special">(</span><span class="identifier">parameter</span><span class="special">)</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">MACRO_CALL_IF_PARAMETER_1</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_IDENTITY</span><span class="special">(</span><span class="identifier">SOME_FIXED_VALUE</span><span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">()</span>
<span class="preprocessor">#define</span> <span class="identifier">MACRO_CALL_IF_PARAMETER_1</span><span class="special">()</span> <span class="identifier">some_processing</span>
</pre>
<p>
The macro BOOST_PP_IDENTITY is actually just:
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">BOOST_PP_IDENTITY</span><span class="special">(</span><span class="identifier">value</span><span class="special">)</span> <span class="identifier">value</span> <span class="identifier">BOOST_PP_EMPTY</span>
</pre>
<p>
so you can see how it is essentially a shorthand for the common case originally
shown at the top of returning a value through the use of BOOST_PP_EMPTY.
</p>
<h5>
<a name="variadic_macro_data.vmd_useful.vmd_identity.h1"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_useful.vmd_identity.using_boost_vmd_empty_and_boost_"></a></span><a class="link" href="vmd_identity.html#variadic_macro_data.vmd_useful.vmd_identity.using_boost_vmd_empty_and_boost_">Using
BOOST_VMD_EMPTY and BOOST_VMD_IDENTITY</a>
</h5>
<p>
The one problem when using BOOST_PP_EMPTY and BOOST_PP_IDENTITY is that the
final invocation must be with no parameters. This is very limiting. If the
final invocation must be with one or more parameters you cannot use BOOST_PP_EMPTY
or BOOST_PP_IDENTITY. In other words, making a change to either of our two
examples:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">control</span><span class="special">/</span><span class="identifier">iif</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">facilities</span><span class="special">/</span><span class="identifier">empty</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">MACRO_CHOICE</span><span class="special">(</span><span class="identifier">parameter1</span><span class="special">,</span><span class="identifier">parameter2</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_IIF</span><span class="special">(</span><span class="identifier">parameter1</span><span class="special">)</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">MACRO_CALL_IF_PARAMETER_1</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">SOME_FIXED_VALUE</span> <span class="identifier">BOOST_PP_EMPTY</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">(</span><span class="identifier">parameter2</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">MACRO_CALL_IF_PARAMETER_1</span><span class="special">(</span><span class="identifier">parameter2</span><span class="special">)</span> <span class="identifier">some_processing_using_a_parameter</span>
</pre>
<p>
or
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">control</span><span class="special">/</span><span class="identifier">iif</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">facilities</span><span class="special">/</span><span class="identifier">identity</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">MACRO_CHOICE</span><span class="special">(</span><span class="identifier">parameter1</span><span class="special">,</span><span class="identifier">parameter2</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_IIF</span><span class="special">(</span><span class="identifier">parameter1</span><span class="special">)</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">MACRO_CALL_IF_PARAMETER_1</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_IDENTITY</span><span class="special">(</span><span class="identifier">SOME_FIXED_VALUE</span><span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">(</span><span class="identifier">parameter2</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">MACRO_CALL_IF_PARAMETER_1</span><span class="special">(</span><span class="identifier">parameter2</span><span class="special">)</span> <span class="identifier">some_processing_using_a_parameter</span>
</pre>
<p>
will produce a preprocessing error since the final invocation to either BOOST_PP_EMPTY
or BOOST_PP_IDENTITY can not be done with 1 or more parameters.
</p>
<p>
It would be much more useful if the final invocation could be done with any
number of parameters. This is where using variadic macros solves the problem.
The BOOST_VMD_EMPTY and BOOST_VMD_IDENTITY macros have the exact same functionality
as their Boost PP counterparts but the final invocation can be made with
any number of parameters, and those parameters are just ignored when BOOST_VMD_EMPTY
or BOOST_VMD_IDENTITY is the choice.
</p>
<p>
Now for our two examples we can have:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">control</span><span class="special">/</span><span class="identifier">iif</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">empty</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">MACRO_CHOICE</span><span class="special">(</span><span class="identifier">parameter1</span><span class="special">,</span><span class="identifier">parameter2</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_IIF</span><span class="special">(</span><span class="identifier">parameter1</span><span class="special">)</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">MACRO_CALL_IF_PARAMETER_1</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">SOME_FIXED_VALUE</span> <span class="identifier">BOOST_VMD_EMPTY</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">(</span><span class="identifier">parameter2</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">MACRO_CALL_IF_PARAMETER_1</span><span class="special">(</span><span class="identifier">parameter2</span><span class="special">)</span> <span class="identifier">some_processing_using_parameters</span>
</pre>
<p>
or
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">control</span><span class="special">/</span><span class="identifier">iif</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">identity</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">MACRO_CHOICE</span><span class="special">(</span><span class="identifier">parameter1</span><span class="special">,</span><span class="identifier">parameter2</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_IIF</span><span class="special">(</span><span class="identifier">parameter1</span><span class="special">)</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">MACRO_CALL_IF_PARAMETER_1</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_IDENTITY</span><span class="special">(</span><span class="identifier">SOME_FIXED_VALUE</span><span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">(</span><span class="identifier">parameter2</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">MACRO_CALL_IF_PARAMETER_1</span><span class="special">(</span><span class="identifier">parameter2</span><span class="special">)</span> <span class="identifier">some_processing_using_parameters</span>
</pre>
<p>
and our macros will compile without preprocessing errors and work as expected.
Both BOOST_VMD_EMPTY and BOOST_VMD_IDENTITY will take any number of parameters
in their invocation, which makes them useful for a final invocation no matter
what is being passed.
</p>
<h5>
<a name="variadic_macro_data.vmd_useful.vmd_identity.h2"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_useful.vmd_identity.usage_for_boost_vmd_empty_and_bo"></a></span><a class="link" href="vmd_identity.html#variadic_macro_data.vmd_useful.vmd_identity.usage_for_boost_vmd_empty_and_bo">Usage
for BOOST_VMD_EMPTY and BOOST_VMD_IDENTITY</a>
</h5>
<p>
To use the BOOST_VMD_EMPTY macro either include the general header:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<p>
or include the specific header:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">empty</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<p>
To use the BOOST_VMD_IDENTITY macro either include the general header:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<p>
or include the specific header:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">identity</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<h5>
<a name="variadic_macro_data.vmd_useful.vmd_identity.h3"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_useful.vmd_identity.using_boost_vmd_empty_and_boost0"></a></span><a class="link" href="vmd_identity.html#variadic_macro_data.vmd_useful.vmd_identity.using_boost_vmd_empty_and_boost0">Using
BOOST_VMD_EMPTY and BOOST_VMD_IDENTITY with VC++</a>
</h5>
<p>
Unfortunately the Visual C++ preprocessor has a problem when a macro expands
to something followed by a variadic macro which expands to nothing. This
is the case when using BOOST_VMD_EMPTY following some non-empty expansion,
or the equivalent use of BOOST_VMD_IDENTITY. As strange as it sounds this
VC++ preprocessor problem is normally solved by concatenating the result
using BOOST_PP_CAT with an empty value. But then again the many non-standard
behaviors of VC++ are difficult to understand or even track.
</p>
<p>
In order to make this technique transparent when used with a C++ standard
conforming preprocessor or VC++ non-standard preprocessor you can use the
BOOST_VMD_IDENTITY_RESULT macro passing to it a single parameter which is
a result returned from a macro which uses BOOST_VMD_IDENTITY ( or its equivalent
'value BOOST_VMD_EMPTY' usage ).
</p>
<p>
Given our MACRO_CHOICE example above, if you have another macro invoking
MACRO_CHOICE simply enclose that invocation within BOOST_VMD_IDENTITY_RESULT.
As in the very simple:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">identity</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">CALLING_MACRO_CHOICE</span><span class="special">(</span><span class="identifier">parameter1</span><span class="special">,</span><span class="identifier">parameter2</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_IDENTITY_RESULT</span><span class="special">(</span><span class="identifier">MACRO_CHOICE</span><span class="special">(</span><span class="identifier">parameter1</span><span class="special">,</span><span class="identifier">parameter2</span><span class="special">))</span>
</pre>
<p>
Alternatively you can change MACRO_CHOICE so that its implementation and
usage is:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">preprocessor</span><span class="special">/</span><span class="identifier">control</span><span class="special">/</span><span class="identifier">iif</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">identity</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">MACRO_CHOICE</span><span class="special">(</span><span class="identifier">parameter1</span><span class="special">,</span><span class="identifier">parameter2</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_IDENTITY_RESULT</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_IIF</span><span class="special">(</span><span class="identifier">parameter1</span><span class="special">)</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">MACRO_CALL_IF_PARAMETER_1</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_IDENTITY</span><span class="special">(</span><span class="identifier">SOME_FIXED_VALUE</span><span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">(</span><span class="identifier">parameter2</span><span class="special">)</span> <span class="special">\</span>
<span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">CALLING_MACRO_CHOICE</span><span class="special">(</span><span class="identifier">parameter1</span><span class="special">,</span><span class="identifier">parameter2</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">MACRO_CHOICE</span><span class="special">(</span><span class="identifier">parameter1</span><span class="special">,</span><span class="identifier">parameter2</span><span class="special">)</span>
</pre>
<p>
Using BOOST_VMD_EMPTY and BOOST_VMD_IDENTITY in this way will ensure they
can be used without preprocessing problems with either VC++ or any C++ standard
conforming preprocessor.
</p>
<h5>
<a name="variadic_macro_data.vmd_useful.vmd_identity.h4"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_useful.vmd_identity.usage_for_boost_vmd_identity_res"></a></span><a class="link" href="vmd_identity.html#variadic_macro_data.vmd_useful.vmd_identity.usage_for_boost_vmd_identity_res">Usage
for BOOST_VMD_IDENTITY_RESULT</a>
</h5>
<p>
The macro BOOST_VMD_IDENTITY_RESULT is in the same header file as BOOST_VMD_IDENTITY,
so to use the BOOST_VMD_IDENTITY_RESULT macro either include the general
header:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<p>
or include the specific header:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">identity</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../vmd_useful.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../vmd_useful.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_empty_ppdata.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,69 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Visual C++ define</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="prev" href="vmd_vmacros.html" title="Using variadic macros">
<link rel="next" href="vmd_detail.html" title="Functional groups">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_vmacros.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_detail.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="variadic_macro_data.vmd_vc"></a><a class="link" href="vmd_vc.html" title="Visual C++ define">Visual C++ define</a>
</h2></div></div></div>
<p>
Microsoft's Visual C++ compiler, abbreviated VC++, is a very popular compiler
but does not implement the standard C++ preprocessor correctly in a number
of respects. Because of this the programmer using the VMD needs to occasionally
do things differently when VC++ is being used. These "quirks" of
VC++ have been smoothed over as much as possible in the VMD library, but are
mentioned in further topics and occasionally must be addressed by the programmer
using VMD.
</p>
<p>
The VMD has a macro that indicates when VC++ is the compiler being used. The
macro is an object-like macro called BOOST_VMD_MSVC. It is set to 1 when VC++
is being used and set to 0 when VC++ is not being used. You can use this macro
in your own macro code whenever you include a VMD header file to write code
which may need special processing for VC++ as outlined in this documentation.
Your macro processing may therefore occasional take the form of:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">some_header</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#if</span> <span class="identifier">BOOST_VMD_MSVC</span>
<span class="preprocessor">#define</span> <span class="identifier">SOME_MACRO</span> <span class="special">...</span> <span class="identifier">code</span> <span class="keyword">for</span> <span class="identifier">VC</span><span class="special">++</span>
<span class="preprocessor">#else</span>
<span class="preprocessor">#define</span> <span class="identifier">SOME_MACRO</span> <span class="special">...</span> <span class="identifier">code</span> <span class="keyword">for</span> <span class="identifier">all</span> <span class="identifier">other</span> <span class="identifier">compilers</span>
<span class="preprocessor">#endif</span>
</pre>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_vmacros.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_detail.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,84 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Visual C++ gotchas in VMD</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="prev" href="vmd_dynamic_typing.html" title="Input as dynamic types">
<link rel="next" href="vmd_conv.html" title="Version 1.7 to 1.8 conversion">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_dynamic_typing.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_conv.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="variadic_macro_data.vmd_vc_isms"></a><a class="link" href="vmd_vc_isms.html" title="Visual C++ gotchas in VMD">Visual C++ gotchas in
VMD</a>
</h2></div></div></div>
<p>
I have discussed throughout the documentation areas of VMD which need to be
considered when using Microsoft's Visual C++ compilers. The VMD library supports
VC++ versions 8 through the latest 14. These correspond to Visual Studio 2005
through the current Visual Studio 2015.
</p>
<p>
I will give here fairly briefly the VC++ quirks which should be taken into
account when using VMD. These quirks exist because the VC++ compiler does not
have a C++ standard conforming preprocessor. More specifically the VC++ compiler
does not follow all of the rules correctly for expanding a macro when a macro
is invoked. Here is a list for things to consider when using VMD with VC++:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
The BOOST_VMD_IS_EMPTY macro will expand erroneously to 1 if the input
resolves to a function-like macro name, which when it is called with an
empty parameter expands to a tuple.
</li>
<li class="listitem">
The BOOST_VMD_ASSERT macro, and the corresponding individual VMD ASSERT
macros for the various data types, do not cause an immediate compiler error,
but instead generate invalid C++ if the ASSERT occurs.
</li>
<li class="listitem">
When the BOOST_VMD_ASSERT macro, or one of the corresponding individual
VMD ASSERT macros for the various data types, does not generate an error,
and the macro in which it is being used does generate some output, it is
necessary to use BOOST_PP_CAT to concatenate the empty result of the VMD
ASSERT macro with the normally generated output to correctly generate the
final expansion of the macro in which the VMD ASSERT occurs.
</li>
<li class="listitem">
When using BOOST_VMD_EMPTY following some non-empty expansion, or when
using BOOST_VMD_IDENTITY, the value returned needs to be concatenated using
BOOST_PP_CAT with an empty value. You can use BOOST_VMD_IDENTITY_RESULT
to accomplish this transparently.
</li>
<li class="listitem">
Avoid using an empty parenthesis to pass no data as a tuple or seq if VC++8
might be used as the compiler.
</li>
</ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_dynamic_typing.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_conv.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,90 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Using variadic macros</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="prev" href="vmd_whyhow.html" title="Why and how to use">
<link rel="next" href="vmd_vc.html" title="Visual C++ define">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_whyhow.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_vc.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="variadic_macro_data.vmd_vmacros"></a><a class="link" href="vmd_vmacros.html" title="Using variadic macros">Using variadic macros</a>
</h2></div></div></div>
<p>
Variadic macros, as specified by C++11, is a feature taken from the C99 specification.
They are macros which take a final parameter denoted as '...' which represents
one or more final arguments to the macro as a series of comma-separated tokens.
In the macro expansion a special keyword of '__VA_ARGS__' represents the comma-separated
tokens. This information when passed to a variadic macro I call 'variadic macro
data', which gives its name to this library. The more general term 'variadic
data' is used in this documentation to specify data passed to a macro which
can contain any number of macro tokens as a single macro parameter, such as
is found in Boost PP data types.
</p>
<h4>
<a name="variadic_macro_data.vmd_vmacros.h0"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_vmacros.boost_support"></a></span><a class="link" href="vmd_vmacros.html#variadic_macro_data.vmd_vmacros.boost_support">Boost
support</a>
</h4>
<p>
The Boost PP library has support for variadic macros and uses its own criteria
to determine if a particular compiler has that support. Boost PP defines or
uses the macro BOOST_PP_VARIADICS to denote whether the compiler being used
supports variadic macros. When BOOST_PP_VARIADICS is set to 1 the compiler
supports variadic macros, otherwise when BOOST_PP_VARIADICS is set to 0 the
compiler does not support variadic macros. If a user of Boost PP sets this
value, Boost PP uses the value the end-user sets, otherwise Boost PP defines
the value of BOOST_PP_VARIADICS based on its own analysis of the compiler being
used. This macro can also be checked to determine if a compiler has support
for variadic macros.
</p>
<h4>
<a name="variadic_macro_data.vmd_vmacros.h1"></a>
<span class="phrase"><a name="variadic_macro_data.vmd_vmacros.determining_variadic_macro_suppo"></a></span><a class="link" href="vmd_vmacros.html#variadic_macro_data.vmd_vmacros.determining_variadic_macro_suppo">Determining
variadic macro support</a>
</h4>
<p>
The VMD library automatically determines whether variadic macro support is
enabled for a particular compiler by also using the same BOOST_PP_VARIADICS
macro from Boost PP. The end-user of VMD can also manually set the macro BOOST_PP_VARIADICS
to turn on or off compiler support for variadic macros in the VMD library.
When BOOST_PP_VARIADICS is set to 0 variadic macros are not supported in the
VMD library, otherwise when BOOST_PP_VARIADICS is set to non-zero they are
supported in the VMD library. This same macro can be used to determine if VMD
supports variadic macros for a particular compiler.
</p>
<p>
Since this library depends on variadic macro support, if BOOST_PP_VARIADICS
is set to 0, using any of the macros in VMD will lead to a compiler error since
the macro will not be defined. However just including any of the header files
in VMD, even with no variadic macro support for the compiler, will not lead
to any compiler errors.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_whyhow.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_vc.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,219 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Why and how to use</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;The Variadic Macro Data Library 1.9">
<link rel="prev" href="vmd_naming.html" title="Naming conventions">
<link rel="next" href="vmd_vmacros.html" title="Using variadic macros">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_naming.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_vmacros.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="variadic_macro_data.vmd_whyhow"></a><a class="link" href="vmd_whyhow.html" title="Why and how to use">Why and how to use</a>
</h2></div></div></div>
<p>
The VMD library provides the ability to create a macro which takes different
types of parameters and can therefore generate different output depending on
the parameter types as well as their values.
</p>
<p>
This is equivalent to the way that overloaded functions provide the ability
for a singularly named function to provide different functionality depending
on the parameter types.
</p>
<p>
In the case of macros, where more than one macro of the same name but different
macro expansion is not allowed, a single macro name can create different expansions.
</p>
<p>
As a simple example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_seq</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_tuple</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">AMACRO</span><span class="special">(</span><span class="identifier">param</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_IIF</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_IS_SEQ</span><span class="special">(</span><span class="identifier">param</span><span class="special">),</span> <span class="special">\</span>
<span class="identifier">Seq</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_IIF</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_IS_TUPLE</span><span class="special">(</span><span class="identifier">param</span><span class="special">),</span> <span class="special">\</span>
<span class="identifier">Tuple</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">Unknown</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">)</span>
</pre>
<p>
If the param passed is a seq the output of the macro is 'Seq'. If the param
passed is a tuple the output of the macro is 'Tuple'. Otherwise the output
of the macro is 'Unknown'.
</p>
<p>
Obviously much more complicated cases can be created in which the types and
values of various parameters are parsed in order to produce variable macro
output depending on the input. Using variadic macros, macros with variable
numbers and types of arguments give the macro programmer even greater freedom
to design macros with flexibility.
</p>
<p>
Another feature of the VMD library is the ability to parse identifiers. A system
of registering identifiers which VMD can recognize has been created. Once an
identifier is registered VMD can recognize it as part of macro input as an
identifier and return the identifier. Furthermore VMD can compare identifiers
for equality or inequality once an identifier has been pre-detected using VMD's
system for pre-detecting identifiers.
</p>
<p>
As another simple example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_identifier</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_NAME</span> <span class="special">(</span><span class="identifier">NAME</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_ADDRESS</span> <span class="special">(</span><span class="identifier">ADDRESS</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">AMACRO1</span><span class="special">(</span><span class="identifier">param</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_IIF</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_IS_IDENTIFIER</span><span class="special">(</span><span class="identifier">param</span><span class="special">),</span> <span class="special">\</span>
<span class="identifier">AMACRO1_IDENTIFIER</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">AMACRO1_NO_IDENTIFIER</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">(</span><span class="identifier">param</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">AMACRO1_IDENTIFIER</span><span class="special">(</span><span class="identifier">param</span><span class="special">)</span> <span class="identifier">AMACRO1_</span> <span class="special">##</span> <span class="identifier">param</span>
<span class="preprocessor">#define</span> <span class="identifier">AMACRO1_NO_IDENTIFIER</span><span class="special">(</span><span class="identifier">param</span><span class="special">)</span> <span class="identifier">Parameter</span> <span class="identifier">is</span> <span class="keyword">not</span> <span class="identifier">an</span> <span class="identifier">identifier</span>
<span class="preprocessor">#define</span> <span class="identifier">AMACRO1_NAME</span> <span class="identifier">Identifier</span> <span class="identifier">is</span> <span class="identifier">a</span> <span class="identifier">NAME</span>
<span class="preprocessor">#define</span> <span class="identifier">AMACRO1_ADDRESS</span> <span class="identifier">Identifier</span> <span class="identifier">is</span> <span class="identifier">an</span> <span class="identifier">ADDRESS</span>
</pre>
<p>
Here we use VMD's identifier registration system to determine and handle a
particular identifier we may be expecting as a macro parameter. If the input
to 'AMACRO1' is 'NAME' the output is 'Identifier is a NAME'. If the input to
'AMACRO1' is 'ADDRESS' the output is 'Identifier is an ADDRESS'. Otherwise
the output is 'Parameter is not an identifier'.
</p>
<p>
Identifier pre-detection makes things clearer, allowing us to detect within
VMD whether macro input matches a particular identifier. Using the same setup
as our previous example, but with identifier pre-detection:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_identifier</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_NAME</span> <span class="special">(</span><span class="identifier">NAME</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_NAME_NAME</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_ADDRESS</span> <span class="special">(</span><span class="identifier">ADDRESS</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_ADDRESS_ADDRESS</span>
<span class="preprocessor">#define</span> <span class="identifier">AMACRO2</span><span class="special">(</span><span class="identifier">param</span><span class="special">)</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_IIF</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_IS_IDENTIFIER</span><span class="special">(</span><span class="identifier">param</span><span class="special">,</span><span class="identifier">NAME</span><span class="special">),</span> <span class="special">\</span>
<span class="identifier">AMACRO2_NAME</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">BOOST_PP_IIF</span> <span class="special">\</span>
<span class="special">(</span> <span class="special">\</span>
<span class="identifier">BOOST_VMD_IS_IDENTIFIER</span><span class="special">(</span><span class="identifier">param</span><span class="special">,</span><span class="identifier">ADDRESS</span><span class="special">),</span> <span class="special">\</span>
<span class="identifier">AMACRO2_ADDRESS</span><span class="special">,</span> <span class="special">\</span>
<span class="identifier">AMACRO2_NO_IDENTIFIER</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">)</span> <span class="special">\</span>
<span class="special">(</span><span class="identifier">param</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">AMACRO2_NO_IDENTIFIER</span><span class="special">(</span><span class="identifier">param</span><span class="special">)</span> <span class="identifier">Parameter</span> <span class="identifier">is</span> <span class="keyword">not</span> <span class="identifier">a</span> <span class="identifier">NAME</span> <span class="keyword">or</span> <span class="identifier">ADDRESS</span> <span class="identifier">identifier</span>
<span class="preprocessor">#define</span> <span class="identifier">AMACRO2_NAME</span><span class="special">(</span><span class="identifier">param</span><span class="special">)</span> <span class="identifier">Identifier</span> <span class="identifier">is</span> <span class="identifier">a</span> <span class="identifier">NAME</span>
<span class="preprocessor">#define</span> <span class="identifier">AMACRO2_ADDRESS</span><span class="special">(</span><span class="identifier">param</span><span class="special">)</span> <span class="identifier">Identifier</span> <span class="identifier">is</span> <span class="identifier">an</span> <span class="identifier">ADDRESS</span>
</pre>
<p>
If the input to 'AMACRO2' is 'NAME' the output is 'Identifier is a NAME'. If
the input to 'AMACRO2' is 'ADDRESS' the output is 'Identifier is an ADDRESS'.
Otherwise the output is 'Parameter is not a NAME or ADDRESS identifier'.
</p>
<p>
The VMD library also has 2 different subtypes of identifiers which can always
be recognized. The first are numbers, equivalent to the number in Boost PP,
numeric values with a range of 0-256. The second are v-types, which are identifiers
starting with BOOST_VMD_TYPE_ followed by a name for the type of data. As an
example, the v-type of a Boost PP tuple is BOOST_VMD_TYPE_TUPLE and the v-type
of a v-type itself is BOOST_VMD_TYPE_TYPE. All data types have their own v-type
identifier; types are recognized by the VMD macros and may be passed as input
data just like any other of the types of data VMD recognizes.
</p>
<p>
The VMD identifier system even has a way, to be explained later, for the end-user
to create his own subtype identifiers.
</p>
<p>
Another reason to use VMD is that VMD understands 'sequences' of the VMD data
types. You can have a sequence of data types and VMD can convert the sequence
to any of the Boost PP data types, or access any individual data type in a
sequence.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">elem</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">to_tuple</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_NAME</span> <span class="special">(</span><span class="identifier">NAME</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">ASEQUENCE</span> <span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">)</span> <span class="identifier">NAME</span> <span class="number">147</span> <span class="identifier">BOOST_VMD_TYPE_NUMBER</span> <span class="special">(</span><span class="identifier">a</span><span class="special">)(</span><span class="identifier">b</span><span class="special">)</span>
<span class="identifier">BOOST_VMD_TO_TUPLE</span><span class="special">(</span><span class="identifier">ASEQUENCE</span><span class="special">)</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">2</span><span class="special">,</span><span class="identifier">ASEQUENCE</span><span class="special">)</span>
</pre>
<p>
Our first expansion returns the tuple:
</p>
<pre class="programlisting"><span class="special">((</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">),</span><span class="identifier">NAME</span><span class="special">,</span><span class="number">147</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_NUMBER</span><span class="special">,(</span><span class="identifier">a</span><span class="special">)(</span><span class="identifier">b</span><span class="special">))</span>
</pre>
<p>
Our second expansion returns the sequence element:
</p>
<pre class="programlisting"><span class="number">147</span>
</pre>
<p>
Sequences give the macro programmer the ability to accept input data from the
user which may more closely mimic C++ constructs.
</p>
<p>
Another reason to use VMD is that VMD understands data types. Besides specifically
asking if a particular input is a particular data type, you can use the macro
BOOST_VMD_GET_TYPE to retrieve the type of any VMD data.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">get_type</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">((</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">))</span> <span class="comment">// expands to BOOST_VMD_TYPE_TUPLE</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="number">235</span><span class="special">)</span> <span class="comment">// expands to BOOST_VMD_TYPE_NUMBER</span>
</pre>
<p>
etc.
</p>
<p>
There is still much more of VMD functionality but hopefully this brief introduction
of what VMD can do will interest you so that you will read on to understand
VMD's functionality for the macro programmer.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_naming.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_vmacros.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>