vmd_useful.html 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. <html>
  2. <head>
  3. <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
  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&#160;1.&#160;The Variadic Macro Data Library 1.9">
  8. <link rel="up" href="../index.html" title="Chapter&#160;1.&#160;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. <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>
  229. <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>
  230. <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>
  231. </pre>
  232. <p>
  233. but for VC++ we must write
  234. </p>
  235. <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>
  236. <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>
  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">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>
  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">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>
  239. <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>
  240. <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>
  241. <span class="identifier">BOOST_PP_CAT</span> <span class="special">\</span>
  242. <span class="special">(</span> <span class="special">\</span>
  243. <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>
  244. <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>
  245. <span class="special">)</span>
  246. </pre>
  247. <p>
  248. VC++ does not work correctly in the first instance, erroneously getting confused
  249. as far as compiler output is concerned. But by using BOOST_PP_CAT in the
  250. second condition VC++ will work correctly with VMD assertions.
  251. </p>
  252. </div>
  253. </div>
  254. <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
  255. <td align="left"></td>
  256. <td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
  257. East Inc</div></td>
  258. </tr></table>
  259. <hr>
  260. <div class="spirit-nav">
  261. <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>
  262. </div>
  263. </body>
  264. </html>