• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<html>
2<head>
3<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
4<title>Useful variadic macros not in Boost PP</title>
5<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
6<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
7<link rel="home" href="../index.html" title="Chapter 1. The Variadic Macro Data Library 1.9">
8<link rel="up" href="../index.html" title="Chapter 1. The Variadic Macro Data Library 1.9">
9<link rel="prev" href="vmd_identifier_subtype.html" title="Identifier subtypes">
10<link rel="next" href="vmd_useful/vmd_identity.html" title="Generating emptiness and identity">
11</head>
12<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
13<table cellpadding="2" width="100%"><tr>
14<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
15<td align="center"><a href="../../../../../index.html">Home</a></td>
16<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
17<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
18<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
19<td align="center"><a href="../../../../../more/index.htm">More</a></td>
20</tr></table>
21<hr>
22<div class="spirit-nav">
23<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>
24</div>
25<div class="section">
26<div class="titlepage"><div><div><h2 class="title" style="clear: both">
27<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
28    not in Boost PP</a>
29</h2></div></div></div>
30<div class="toc"><dl class="toc">
31<dt><span class="section"><a href="vmd_useful.html#variadic_macro_data.vmd_useful.vmd_assert">Asserting
32      and data types</a></span></dt>
33<dt><span class="section"><a href="vmd_useful/vmd_identity.html">Generating
34      emptiness and identity</a></span></dt>
35<dt><span class="section"><a href="vmd_useful/vmd_empty_ppdata.html">Functionality
36      for "empty" seqs and tuples</a></span></dt>
37</dl></div>
38<p>
39      Previous sections of this documentation have explained how VMD can be used
40      to parse VMD data types, as well as recognize emptiness.
41    </p>
42<p>
43      Another area of functionality of VMD involves useful variadic macros, based
44      on the previous functionality, which expands on similar macros already in Boost
45      PP. These variadic macros can be divided into sections illustrating these areas
46      of behavior:
47    </p>
48<div class="orderedlist"><ol class="orderedlist" type="1">
49<li class="listitem">
50          Expanded assertion macros
51        </li>
52<li class="listitem">
53          Expanded identity functionality
54        </li>
55<li class="listitem">
56          Expanded seq and tuple functionality for "empty" seqs and tuples
57        </li>
58</ol></div>
59<p>
60      Sub-sections for each of these now follow in the documentation.
61    </p>
62<div class="section">
63<div class="titlepage"><div><div><h3 class="title">
64<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
65      and data types</a>
66</h3></div></div></div>
67<p>
68        The VMD macros for identifying data types work best when the macro logic
69        can take different paths depending on the type of data being passed for a
70        macro parameter. But occasionally the preprocessor metaprogrammer wants to
71        simply verify that the macro parameter data is of the correct data type,
72        else a preprocessing error should be generated to notify the programmer invoking
73        the macro that the data passed is the incorrect type.
74      </p>
75<h5>
76<a name="variadic_macro_data.vmd_useful.vmd_assert.h0"></a>
77        <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
78        BOOST_VMD_ASSERT</a>
79      </h5>
80<p>
81        The Boost PP library has a macro which produces a preprocessing error when
82        the condition passed to it is 0. This macro is called BOOST_PP_ASSERT. The
83        macro produces a preprocessor error by forcing a call to an internal macro
84        with the wrong number of arguments. According to the C++ standard this should
85        always cause an immediate preprocessing error for conforming compilers.
86      </p>
87<p>
88        Unfortunately VC++ will only produce a warning when the wrong number of arguments
89        are passed to a macro. Therefore the BOOST_PP_ASSERT macro does not produce
90        a preprocessing error using VC++. Amazingly enough there appears to be no
91        other way in which VC++ can be forced to issue a preprocessing error by invoking
92        a macro ( if you find one please tell me about it ). However one can create
93        invalid C++ as the output from a macro invocation which causes VC++ to produce
94        a compiler error when the VC++ compiler later encounters the construct.
95      </p>
96<p>
97        This is what the macro BOOST_VMD_ASSERT does. It takes the same conditional
98        argument as BOOST_PP_ASSERT and it calls BOOST_PP_ASSERT when not used with
99        VC++, otherwise if the condition is 0 it generates a compiler error by generating
100        invalid C++ when used with VC++. The compiler error is generated by producing
101        invalid C++ whose form is:
102      </p>
103<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>
104</pre>
105<p>
106        By passing a second optional argument, whose form is a preprocessing identifier,
107        to BOOST_VMD_ASSERT you can generate the invalid C++ for VC++, if the first
108        argument is 0, of the form:
109      </p>
110<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>
111</pre>
112<p>
113        instead. This may give a little more clarity, if desired, to the C++ error
114        generated.
115      </p>
116<p>
117        If the first conditional argument is not 0, BOOST_VMD_ASSERT produces no
118        output.
119      </p>
120<h5>
121<a name="variadic_macro_data.vmd_useful.vmd_assert.h1"></a>
122        <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
123        Usage</a>
124      </h5>
125<p>
126        To use the BOOST_VMD_ASSERT macro either include the general header:
127      </p>
128<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>
129</pre>
130<p>
131        or include the specific header:
132      </p>
133<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>
134</pre>
135<h5>
136<a name="variadic_macro_data.vmd_useful.vmd_assert.h2"></a>
137        <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
138        for data types </a>
139      </h5>
140<p>
141        The data types have their own assertion macros. These are largely just shortcuts
142        for passing the result of the identifying macros to BOOST_VMD_ASSERT. These
143        assertion macros are:
144      </p>
145<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
146<li class="listitem">
147            emptiness, BOOST_VMD_ASSERT_IS_EMPTY
148          </li>
149<li class="listitem">
150            identifier, BOOST_VMD_ASSERT_IS_IDENTIFIER
151          </li>
152<li class="listitem">
153            number, BOOST_VMD_ASSERT_IS_NUMBER
154          </li>
155<li class="listitem">
156            array, BOOST_VMD_ASSERT_IS_ARRAY
157          </li>
158<li class="listitem">
159            list, BOOST_VMD_ASSERT_IS_LIST
160          </li>
161<li class="listitem">
162            seq, BOOST_VMD_ASSERT_IS_SEQ
163          </li>
164<li class="listitem">
165            tuple, BOOST_VMD_ASSERT_IS_TUPLE
166          </li>
167<li class="listitem">
168            type, BOOST_VMD_ASSERT_IS_TYPE
169          </li>
170</ul></div>
171<p>
172        Each of these macros take as parameters the exact same argument as their
173        corresponding identifying macros. But instead of returning non-zero or 0,
174        each of these macros produce a compiler error if the type of the input is
175        not correct.
176      </p>
177<p>
178        Each of these macros only check for its assertion when the macro BOOST_VMD_ASSERT_DATA
179        is set to 1. By default BOOST_VMD_ASSERT_DATA is only set to 1 in compiler
180        debug mode. The programmer can manually set BOOST_VMD_ASSERT_DATA to 1 prior
181        to using one the data types assert macros if he wishes.
182      </p>
183<h5>
184<a name="variadic_macro_data.vmd_useful.vmd_assert.h3"></a>
185        <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_...
186        Usage</a>
187      </h5>
188<p>
189        To use the individual BOOST_VMD_ASSERT_... macros either include the general
190        header:
191      </p>
192<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>
193</pre>
194<p>
195        or include the specific header:
196      </p>
197<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>
198<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>
199<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>
200<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>
201<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>
202<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>
203<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>
204<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>
205</pre>
206<h5>
207<a name="variadic_macro_data.vmd_useful.vmd_assert.h4"></a>
208        <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
209        and VC++ </a>
210      </h5>
211<p>
212        The VC++ compiler has a quirk when dealing with BOOST_VMD_ASSERT and the
213        data type assert macros. If you invoke one of the assert macros within another
214        macro which would normally generate output preprocessor tokens, it is necessary
215        when using VC++ to concatenate the result of the assert macro to whatever
216        other preprocessor data is being generated, even if the assert macro does
217        not generate an error.
218      </p>
219<p>
220        As a simple example let us suppose we have a macro expecting a tuple and
221        generating 1 if the tuple has more than 2 elements, otherwise it generates
222        0. Ordinarily we could write:
223      </p>
224<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>
225<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>
226<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>
227<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>
228
229<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>
230    <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>
231    <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>
232</pre>
233<p>
234        but for VC++ we must write
235      </p>
236<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>
237<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>
238<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>
239<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>
240<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>
241
242<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>
243    <span class="identifier">BOOST_PP_CAT</span> <span class="special">\</span>
244       <span class="special">(</span> <span class="special">\</span>
245       <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>
246       <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>
247       <span class="special">)</span>
248</pre>
249<p>
250        VC++ does not work correctly in the first instance, erroneously getting confused
251        as far as compiler output is concerned. But by using BOOST_PP_CAT in the
252        second condition VC++ will work correctly with VMD assertions.
253      </p>
254</div>
255</div>
256<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
257<td align="left"></td>
258<td align="right"><div class="copyright-footer">Copyright © 2010-2017 Tropic Software
259      East Inc</div></td>
260</tr></table>
261<hr>
262<div class="spirit-nav">
263<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>
264</div>
265</body>
266</html>
267