271 lines
22 KiB
HTML
271 lines
22 KiB
HTML
<html>
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||
<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 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_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++ with its default preprocessor 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++ with its default
|
||
preprocessor. Amazingly enough there appears to be no other way in which
|
||
VC++ with its default preprocessor 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++ with its default preprocessor, otherwise if the condition is 0 it generates
|
||
a compiler error by generating invalid C++ when used with VC++ with its default
|
||
preprocessor. 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++ with its default
|
||
preprocessor, 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"><</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">></span>
|
||
</pre>
|
||
<p>
|
||
or include the specific header:
|
||
</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">assert</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></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"><</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">></span>
|
||
</pre>
|
||
<p>
|
||
or include the specific header:
|
||
</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">assert_is_empty</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> <span class="comment">// BOOST_VMD_ASSERT_IS_EMPTY</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">assert_is_identifier</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> <span class="comment">// BOOST_VMD_ASSERT_IS_IDENTIFIER</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">assert_is_number</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> <span class="comment">// BOOST_VMD_ASSERT_IS_NUMBER</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">assert_is_array</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> <span class="comment">// BOOST_VMD_ASSERT_IS_ARRAY</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">assert_is_list</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> <span class="comment">// BOOST_VMD_ASSERT_IS_LIST</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">assert_is_seq</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> <span class="comment">// BOOST_VMD_ASSERT_IS_SEQ</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">assert_is_tuple</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> <span class="comment">// BOOST_VMD_ASSERT_IS_TUPLE</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">assert_is_type</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></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 with its default preprocessor 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++ with its default preprocessor
|
||
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"><</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">></span>
|
||
<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">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">></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">assert_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">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++ with its default preprocessor we must write
|
||
</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">cat</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">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">></span>
|
||
<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">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">></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">assert_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">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++ with its default preprocessor 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++ with its default preprocessor
|
||
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 © 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>
|