123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- <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>
|