222 lines
21 KiB
HTML
222 lines
21 KiB
HTML
<html>
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||
<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 1. The Variadic Macro Data Library 1.10">
|
||
<link rel="up" href="../index.html" title="Chapter 1. The Variadic Macro Data Library 1.10">
|
||
<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"><</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">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</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">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</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">></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. VMD
|
||
can recognize general identifiers as well as recognize specific identifiers,
|
||
which have been registered. Once an identifier is registered VMD can recognize
|
||
it as part of VMD sequences. Furthermore VMD can compare identifiers for equality
|
||
or inequality once a specific 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"><</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">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">is_general_identifier</span><span class="special">.</span><span class="identifier">hpp</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_GENERAL_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 ability to recoghnize general identifiers 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 registration and 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 registration and
|
||
pre-detection:
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</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">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</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">></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-BOOST_PP_LIMIT_MAG. 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. Idewntifiers in VMD sequences must be registered to be recognized.
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</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">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</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">></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 <code class="computeroutput"><span class="identifier">BOOST_VMD_TO_TUPLE</span><span class="special">(</span><span class="identifier">ASEQUENCE</span><span class="special">)</span></code> 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 <code class="computeroutput"><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></code>
|
||
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"><</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">></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 © 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>
|