267 lines
22 KiB
HTML
267 lines
22 KiB
HTML
<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 1. The Variadic Macro Data Library 1.9">
|
|
<link rel="up" href="../index.html" title="Chapter 1. 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"><</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 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"><</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++ 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++ 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 © 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>
|