vmd_specific.html 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. <html>
  2. <head>
  3. <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
  4. <title>Specific macros for working with data types</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_data_types.html" title="Data types">
  10. <link rel="next" href="vmd_specific/vmd_constraints.html" title="Macro constraints">
  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_data_types.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_specific/vmd_constraints.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_specific"></a><a class="link" href="vmd_specific.html" title="Specific macros for working with data types">Specific macros for working
  28. with data types</a>
  29. </h2></div></div></div>
  30. <div class="toc"><dl class="toc">
  31. <dt><span class="section"><a href="vmd_specific.html#variadic_macro_data.vmd_specific.vmd_test_empty">Emptiness</a></span></dt>
  32. <dt><span class="section"><a href="vmd_specific/vmd_constraints.html">Macro
  33. constraints</a></span></dt>
  34. <dt><span class="section"><a href="vmd_specific/vmd_identifier.html">Identifiers</a></span></dt>
  35. <dt><span class="section"><a href="vmd_specific/vmd_number.html">Numbers</a></span></dt>
  36. <dt><span class="section"><a href="vmd_specific/vmd_type.html">Types</a></span></dt>
  37. <dt><span class="section"><a href="vmd_specific/vmd_pp_data_types.html">VMD
  38. and Boost PP data types</a></span></dt>
  39. <dt><span class="section"><a href="vmd_specific/vmd_identifying.html">Identifying
  40. data types</a></span></dt>
  41. </dl></div>
  42. <p>
  43. VMD has a number of specific macros for parsing data types. Each of these macros
  44. asks if some input is a particular VMD data type.
  45. </p>
  46. <div class="section">
  47. <div class="titlepage"><div><div><h3 class="title">
  48. <a name="variadic_macro_data.vmd_specific.vmd_test_empty"></a><a class="link" href="vmd_specific.html#variadic_macro_data.vmd_specific.vmd_test_empty" title="Emptiness">Emptiness</a>
  49. </h3></div></div></div>
  50. <h5>
  51. <a name="variadic_macro_data.vmd_specific.vmd_test_empty.h0"></a>
  52. <span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_test_empty.passing_empty_arguments"></a></span><a class="link" href="vmd_specific.html#variadic_macro_data.vmd_specific.vmd_test_empty.passing_empty_arguments">Passing
  53. empty arguments</a>
  54. </h5>
  55. <p>
  56. It is possible to pass an empty argument to a macro. The official terminology
  57. for this in the C++ standard is an argument "consisting of no preprocessing
  58. tokens".
  59. </p>
  60. <p>
  61. Let us consider a number of cases without worrying too much what the macro
  62. output represents.
  63. </p>
  64. <p>
  65. Consider these two function-like macros:
  66. </p>
  67. <pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">SMACRO</span><span class="special">()</span> <span class="identifier">someoutput</span>
  68. <span class="preprocessor">#define</span> <span class="identifier">EMACRO</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span> <span class="identifier">otheroutput</span> <span class="identifier">x</span>
  69. </pre>
  70. <p>
  71. The first macro takes no parameters so invoking it must always be done by
  72. </p>
  73. <pre class="programlisting"><span class="identifier">SMACRO</span><span class="special">()</span>
  74. </pre>
  75. <p>
  76. and passing any arguments to it would be invalid.
  77. </p>
  78. <p>
  79. The second macro takes a single parameter. it can be evoked as
  80. </p>
  81. <pre class="programlisting"><span class="identifier">EMACRO</span><span class="special">(</span><span class="identifier">somedata</span><span class="special">)</span>
  82. </pre>
  83. <p>
  84. but it also can be invoked as
  85. </p>
  86. <pre class="programlisting"><span class="identifier">EMACRO</span><span class="special">()</span>
  87. </pre>
  88. <p>
  89. In the second invocation of EMACRO we are passing an empty argument to the
  90. macro. Similarly for any macro having 1 or more parameters, an empty argument
  91. can be validly passed for any of the parameters, as in
  92. </p>
  93. <pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">MMACRO</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier">y</span><span class="special">,</span><span class="identifier">z</span><span class="special">)</span> <span class="identifier">x</span> <span class="identifier">y</span> <span class="identifier">z</span>
  94. <span class="identifier">MMACRO</span><span class="special">(</span><span class="number">1</span><span class="special">,,</span><span class="number">2</span><span class="special">)</span>
  95. </pre>
  96. <p>
  97. An empty argument is an argument even if we are passing nothing.
  98. </p>
  99. <p>
  100. Because an empty argument can be passed for a given parameter of a macro
  101. does not mean one should do so. Any given macro will specify what each argument
  102. to a macro should represent, and it is has normally been very rare to encounter
  103. a macro which specifies that an empty argument can logically be passed for
  104. a given argument. But from the perspective of standard C++ it is perfectly
  105. valid to pass an empty argument for a macro parameter.
  106. </p>
  107. <p>
  108. The notion of passing empty arguments can be extended to passing empty data
  109. which "consists of no preprocessing tokens" in slightly more complicated
  110. situations. It is possible to pass empty data as an argument to a variadic
  111. macro in the form of variadic macro data, as in
  112. </p>
  113. <pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">VMACRO</span><span class="special">(</span><span class="identifier">x</span><span class="special">,...)</span> <span class="identifier">x</span> <span class="identifier">__VA_ARGS__</span>
  114. </pre>
  115. <p>
  116. invoked as
  117. </p>
  118. <pre class="programlisting"><span class="identifier">VMACRO</span><span class="special">(</span><span class="identifier">somedata</span><span class="special">,)</span>
  119. </pre>
  120. <p>
  121. Here one passes empty data as the variadic macro data and it is perfectly
  122. valid C++. Please notice that this different from
  123. </p>
  124. <pre class="programlisting"><span class="identifier">VMACRO</span><span class="special">(</span><span class="identifier">somedata</span><span class="special">)</span>
  125. </pre>
  126. <p>
  127. which is not valid C++, prior to C++20, since something must be passed for
  128. the variadic argument. In C++20 the above invocation is valid and is exactly
  129. the same as in our previous example of 'VMACRO(somedata,)' where one passes
  130. empty data as the variadic macro data. Similarly one could invoke the macro
  131. as
  132. </p>
  133. <pre class="programlisting"><span class="identifier">VMACRO</span><span class="special">(</span><span class="identifier">somedata</span><span class="special">,</span><span class="identifier">vdata1</span><span class="special">,,</span><span class="identifier">vdata3</span><span class="special">)</span>
  134. </pre>
  135. <p>
  136. where one is passing variadic macro data but an element in the variadic macro
  137. data is empty.
  138. </p>
  139. <p>
  140. Furthermore if we are invoking a macro which expects a Boost PP data type,
  141. such as a tuple, we could also validly pass empty data for all or part of
  142. the data in a tuple, as in
  143. </p>
  144. <pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">TMACRO</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier">atuple</span><span class="special">)</span> <span class="identifier">x</span> <span class="identifier">atuple</span>
  145. <span class="identifier">TMACRO</span><span class="special">(</span><span class="identifier">somedata</span><span class="special">,())</span>
  146. </pre>
  147. <p>
  148. In this case we are passing a 1 element tuple where the single element itself
  149. is empty.
  150. </p>
  151. <p>
  152. or
  153. </p>
  154. <pre class="programlisting"><span class="identifier">TMACRO</span><span class="special">(</span><span class="identifier">somedata</span><span class="special">,(</span><span class="identifier">telem1</span><span class="special">,,</span><span class="identifier">telem2</span><span class="special">,</span><span class="identifier">teleem3</span><span class="special">))</span>
  155. </pre>
  156. <p>
  157. In this case we are passing a 4 element tuple where the second element is
  158. empty.
  159. </p>
  160. <p>
  161. Again either invocation is valid C++ but it is not necessarily what the designed
  162. of the macro has desired, even if in both cases the macro designer has specified
  163. that the second parameter must be a tuple for the macro to work properly.
  164. </p>
  165. <h5>
  166. <a name="variadic_macro_data.vmd_specific.vmd_test_empty.h1"></a>
  167. <span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_test_empty.returning_emptiness"></a></span><a class="link" href="vmd_specific.html#variadic_macro_data.vmd_specific.vmd_test_empty.returning_emptiness">Returning
  168. emptiness</a>
  169. </h5>
  170. <p>
  171. Similar to passing empty arguments in various ways to a macro, the data which
  172. a macro returns ( or 'generates' may be a better term ) could be empty, in
  173. various ways. Again I am not necessarily promoting this idea as a common
  174. occurrence of macro design but merely pointing it out as valid C++ preprocessing.
  175. </p>
  176. <pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">RMACRO</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier">y</span><span class="special">,</span><span class="identifier">z</span><span class="special">)</span>
  177. <span class="identifier">RMACRO</span><span class="special">(</span><span class="identifier">data1</span><span class="special">,</span><span class="identifier">data2</span><span class="special">,</span><span class="identifier">data3</span><span class="special">)</span>
  178. </pre>
  179. <p>
  180. It is perfectly valid C++ to return "nothing" from a macro invocation.
  181. In fact a number of macros in Boost PP do that based on the preprocessor
  182. metaprogramming logic of the macro, and are documented as such.
  183. </p>
  184. <p>
  185. Similarly one could return nothing as part or all of a Boost PP data type
  186. or even as part of variadic macro data.
  187. </p>
  188. <pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">TRETMACRO</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier">y</span><span class="special">,</span><span class="identifier">z</span><span class="special">)</span> <span class="special">()</span>
  189. <span class="preprocessor">#define</span> <span class="identifier">TRETMACRO1</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier">y</span><span class="special">,</span><span class="identifier">z</span><span class="special">)</span> <span class="special">(</span><span class="identifier">x</span><span class="special">,,</span><span class="identifier">y</span><span class="special">,,</span><span class="identifier">z</span><span class="special">)</span>
  190. <span class="preprocessor">#define</span> <span class="identifier">VRETMACRO</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier">y</span><span class="special">,</span><span class="identifier">z</span><span class="special">)</span> <span class="identifier">x</span><span class="special">,,</span><span class="identifier">y</span><span class="special">,,</span><span class="identifier">z</span>
  191. </pre>
  192. <p>
  193. Here again we are returning something but in terms of a Boost PP tuple or
  194. in terms of variadic data, we have elements which are empty.
  195. </p>
  196. <h5>
  197. <a name="variadic_macro_data.vmd_specific.vmd_test_empty.h2"></a>
  198. <span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_test_empty.emptiness_in_preprocessor_metapr"></a></span><a class="link" href="vmd_specific.html#variadic_macro_data.vmd_specific.vmd_test_empty.emptiness_in_preprocessor_metapr">Emptiness
  199. in preprocessor metaprogramming</a>
  200. </h5>
  201. <p>
  202. In the examples given above where "emptiness" in one form of another
  203. is passed as arguments to a macro or returned from a macro, the examples
  204. I have given were created as simplified as possible to illustrate my points.
  205. In actual preprocessor metaprogramming, using Boost PP, where complicated
  206. logic is used to generate macro output based on the arguments to a macro,
  207. it might be useful to allow and work with empty data if one were able to
  208. test for the fact that data was indeed empty.
  209. </p>
  210. <h5>
  211. <a name="variadic_macro_data.vmd_specific.vmd_test_empty.h3"></a>
  212. <span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_test_empty.testing_for_empty_data"></a></span><a class="link" href="vmd_specific.html#variadic_macro_data.vmd_specific.vmd_test_empty.testing_for_empty_data">Testing
  213. for empty data</a>
  214. </h5>
  215. <p>
  216. Currently Boost PP has an undocumented macro for testing whether a parameter
  217. is empty of not, written without the use of variadic macros. The macro is
  218. called BOOST_PP_IS_EMPTY. The macro is by its nature flawed, since there
  219. is no generalized way of determining whether or not a parameter is empty
  220. using the C++ preprocessor prior to C++20. But the macro will work given
  221. input limited in various ways or if the input is actually empty.
  222. </p>
  223. <p>
  224. Paul Mensonides, the developer of Boost PP and the BOOST_PP_IS_EMPTY macro
  225. in that library, also wrote a better macro using variadic macros, for determining
  226. whether or not a parameter is empty or not, which he published on the Internet
  227. in response to a discussion about emptiness. This macro is also not perfect,
  228. since there is no perfect solution prior to C++20, but will work correctly
  229. with almost all input. I have adapted his code for VMD and developed my own
  230. very slightly different code.
  231. </p>
  232. <p>
  233. The macro is called <code class="computeroutput"><a class="link" href="../BOOST_VMD_IS_EMPTY.html" title="Macro BOOST_VMD_IS_EMPTY">BOOST_VMD_IS_EMPTY</a></code>
  234. and will return 1 if its input is empty or 0 if its input is not empty. The
  235. macro is a variadic macro which make take any input <a href="#ftn.variadic_macro_data.vmd_specific.vmd_test_empty.f0" class="footnote" name="variadic_macro_data.vmd_specific.vmd_test_empty.f0"><sup class="footnote">[1]</sup></a>.
  236. </p>
  237. <h5>
  238. <a name="variadic_macro_data.vmd_specific.vmd_test_empty.h4"></a>
  239. <span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_test_empty.macro_flaw_with_a_standard_c_com"></a></span><a class="link" href="vmd_specific.html#variadic_macro_data.vmd_specific.vmd_test_empty.macro_flaw_with_a_standard_c_com">Macro
  240. Flaw with a standard C++ compiler</a>
  241. </h5>
  242. <p>
  243. The one situation prior to C++20 where the macro does not work properly is
  244. if its input resolves to a function-like macro name or a sequence of preprocessor
  245. tokens ending with a function-like macro name and the function-like macro
  246. takes two or more parameters.
  247. </p>
  248. <p>
  249. Here is a simple example:
  250. </p>
  251. <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">is_empty</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
  252. <span class="preprocessor">#define</span> <span class="identifier">FMACRO</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier">y</span><span class="special">)</span> <span class="identifier">any_output</span>
  253. <span class="identifier">BOOST_VMD_IS_EMPTY</span><span class="special">(</span><span class="identifier">FMACRO</span><span class="special">)</span>
  254. <span class="identifier">BOOST_VMD_IS_EMPTY</span><span class="special">(</span><span class="identifier">some_input</span> <span class="identifier">FMACRO</span><span class="special">)</span>
  255. </pre>
  256. <p>
  257. In the first case the name of a function-like macro is being passed to BOOST_VMD_IS_EMPTY
  258. while in the second case a sequence of preprocessing tokens is being passed
  259. to BOOST_VMD_IS_EMPTY ending with the name of a function-like macro. The
  260. function-like macro also has two ( or more ) parameters. In both the cases
  261. above a compiler error will result from the use of BOOST_VMD_IS_EMPTY.
  262. </p>
  263. <p>
  264. Please note that these two problematical cases are not the same as passing
  265. an invocation of a function-like macro name to BOOST_VMD_IS_EMPTY, as in
  266. </p>
  267. <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">is_empty</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
  268. <span class="identifier">BOOST_VMD_IS_EMPTY</span><span class="special">(</span><span class="identifier">FMACRO</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">,</span><span class="identifier">arg2</span><span class="special">))</span>
  269. <span class="identifier">BOOST_VMD_IS_EMPTY</span><span class="special">(</span><span class="identifier">someinput</span> <span class="identifier">FMACRO</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">,</span><span class="identifier">arg2</span><span class="special">))</span>
  270. </pre>
  271. <p>
  272. which always works correctly, unless of course a particular function-like
  273. macro invocation resolves to either of our two previous situations.
  274. </p>
  275. <p>
  276. Another situation where the macro may not work properly is if the previously
  277. mentioned function-like macro takes a single parameter but creates an error
  278. when the argument passed is empty. An example of this would be:
  279. </p>
  280. <pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">FMACRO</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span> <span class="identifier">BOOST_PP_CAT</span><span class="special">(+,</span><span class="identifier">x</span> <span class="identifier">C</span><span class="special">);</span>
  281. </pre>
  282. <p>
  283. When nothing is passed to FMACRO undefined behavior will occur since attempting
  284. to concatenate '+' to ' C' is UB in C++ preprocessor terms.
  285. </p>
  286. <p>
  287. So for a standard conforming compiler, prior to C++20, we have essentially
  288. two corner cases where the BOOST_VMD_IS_EMPTY does not work and, when it
  289. does not work it, produces a compiler error rather than an incorrect result.
  290. Essentially what is desired for maximum safety is that we never pass input
  291. ending with the name of a function-like macro name when testing for emptiness.
  292. </p>
  293. <h5>
  294. <a name="variadic_macro_data.vmd_specific.vmd_test_empty.h5"></a>
  295. <span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_test_empty.macro_flaw_with_visual_c"></a></span><a class="link" href="vmd_specific.html#variadic_macro_data.vmd_specific.vmd_test_empty.macro_flaw_with_visual_c">Macro
  296. Flaw with Visual C++</a>
  297. </h5>
  298. <p>
  299. The VC++ preprocessor is not a standard C++ conforming preprocessor in at
  300. least two relevant situations to our discussion of emptiness. These situations
  301. combine to create a single corner case which causes the BOOST_VMD_IS_EMPTY
  302. macro to not work properly using VC++ when the input resolves to a function-like
  303. macro name.
  304. </p>
  305. <p>
  306. The first situation, related to our discussion of emptiness, where the VC++
  307. preprocessor is not a standard C++ conforming preprocessor is that if a macro
  308. taking 'n' number of parameters is invoked with 0 to 'n-1' parameters, the
  309. compiler does not give an error, but only a warning.
  310. </p>
  311. <pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">FMACRO</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier">y</span><span class="special">)</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span>
  312. <span class="identifier">FMACRO</span><span class="special">(</span><span class="number">1</span><span class="special">)</span>
  313. </pre>
  314. <p>
  315. should give a compiler error, as it does when using a C++ standard-conforming
  316. compiler, but when invoked using VC++ it only gives a warning and VC++ continues
  317. macro substitution with 'y' as a placemarker preprocessing token. This non-standard
  318. conforming action actually eliminates the case where BOOST_VMD_IS_EMPTY does
  319. not work properly with a standard C++ conforming compiler. But of course
  320. it has the potential of producing incorrect output in other macro processing
  321. situations unrelated to the BOOST_VMD_IS_EMPTY invocation, where a compiler
  322. error should occur.
  323. </p>
  324. <p>
  325. A second general situation, related to our discussion of emptiness, where
  326. the VC++ preprocessor is not a standard C++ conforming preprocessor is that
  327. the expansion of a macro works incorrectly when the expanded macro is a function-like
  328. macro name followed by a function-like macro invocation, in which case the
  329. macro re-expansion is erroneously done more than once. This latter case can
  330. be seen by this example:
  331. </p>
  332. <pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">FMACRO1</span><span class="special">(</span><span class="identifier">parameter</span><span class="special">)</span> <span class="identifier">FMACRO3</span> <span class="identifier">parameter</span><span class="special">()</span>
  333. <span class="preprocessor">#define</span> <span class="identifier">FMACRO2</span><span class="special">()</span> <span class="special">()</span>
  334. <span class="preprocessor">#define</span> <span class="identifier">FMACRO3</span><span class="special">()</span> <span class="number">1</span>
  335. <span class="identifier">FMACRO1</span><span class="special">(</span><span class="identifier">FMACRO2</span><span class="special">)</span>
  336. <span class="identifier">should</span> <span class="identifier">expand</span> <span class="identifier">to</span><span class="special">:</span>
  337. <span class="identifier">FMACRO3</span><span class="special">()</span>
  338. <span class="identifier">but</span> <span class="identifier">in</span> <span class="identifier">VC</span><span class="special">++</span> <span class="identifier">it</span> <span class="identifier">expands</span> <span class="identifier">to</span><span class="special">:</span>
  339. <span class="number">1</span>
  340. </pre>
  341. <p>
  342. where after initially expanding the macro to:
  343. </p>
  344. <pre class="programlisting"><span class="identifier">FMACRO3</span> <span class="identifier">FMACRO2</span><span class="special">()</span>
  345. </pre>
  346. <p>
  347. VC++ erroneously rescans the sequence of preprocessing tokens more than once
  348. rather than rescan just one more time for more macro names.
  349. </p>
  350. <p>
  351. What these two particular preprocessor flaws in the VC++ compiler mean is
  352. that although BOOST_VMD_IS_EMPTY does not fail with a compiler error in the
  353. same case as with a standard C++ conforming compiler given previously, it
  354. fails by giving the wrong result in another situation.
  355. </p>
  356. <p>
  357. The failing situation is:
  358. </p>
  359. <p>
  360. when the input to BOOST_VMD_IS_EMPTY resolves to only a function-like macro
  361. name, and the function-like macro, when passed a single empty argument, expands
  362. to a Boost PP tuple, BOOST_VMD_IS_EMPTY will erroneously return 1 when using
  363. the Visual C++ compiler rather than either give a preprocessing error or
  364. return 0.
  365. </p>
  366. <p>
  367. Here is an example of the failure:
  368. </p>
  369. <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">is_empty</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
  370. <span class="preprocessor">#define</span> <span class="identifier">FMACRO4</span><span class="special">()</span> <span class="special">(</span> <span class="identifier">any_number_of_tuple_elements</span> <span class="special">)</span>
  371. <span class="preprocessor">#define</span> <span class="identifier">FMACRO5</span><span class="special">(</span><span class="identifier">param</span><span class="special">)</span> <span class="special">(</span> <span class="identifier">any_number_of_tuple_elements</span> <span class="special">)</span>
  372. <span class="preprocessor">#define</span> <span class="identifier">FMACRO6</span><span class="special">(</span><span class="identifier">param1</span><span class="special">,</span><span class="identifier">param2</span><span class="special">)</span> <span class="special">(</span> <span class="identifier">any_number_of_tuple_elements</span> <span class="special">)</span>
  373. <span class="identifier">BOOST_VMD_IS_EMPTY</span><span class="special">(</span><span class="identifier">FMACRO4</span><span class="special">)</span> <span class="comment">// erroneously returns 1, instead of 0</span>
  374. <span class="identifier">BOOST_VMD_IS_EMPTY</span><span class="special">(</span><span class="identifier">FMACRO5</span><span class="special">)</span> <span class="comment">// erroneously returns 1, instead of 0</span>
  375. <span class="identifier">BOOST_VMD_IS_EMPTY</span><span class="special">(</span><span class="identifier">FMACRO6</span><span class="special">)</span> <span class="comment">// erroneously returns 1, instead of generating a preprocessing error</span>
  376. </pre>
  377. <p>
  378. As with a standard C++ conforming compiler prior to C++20, we have a rare
  379. corner case where the BOOST_VMD_IS_EMPTY will not work properly, but unfortunately
  380. in this very similar but even rarer corner case with VC++, we will silently
  381. get an incorrect result rather than a compiler error.
  382. </p>
  383. <p>
  384. I want to reiterate that for all compilers prior to C++20 there is no perfect
  385. solution in C++ to the detection of emptiness even for a C++ compiler whose
  386. preprocessor is completely conformant, which VC++ obviously is not.
  387. </p>
  388. <h5>
  389. <a name="variadic_macro_data.vmd_specific.vmd_test_empty.h6"></a>
  390. <span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_test_empty.testing_emptiness_in_c_20_mode"></a></span><a class="link" href="vmd_specific.html#variadic_macro_data.vmd_specific.vmd_test_empty.testing_emptiness_in_c_20_mode">Testing
  391. emptiness in C++20 mode</a>
  392. </h5>
  393. <p>
  394. A few compilers can currently operate in C++20 mode, by which I mean that
  395. you can pass a compiler flag when compiling with such a compiler which enforces
  396. the upcoming C++20 standard. One of the features of the C++20 standard is
  397. the addition of a preprocessor construct called __VA_OPT__. Because of the
  398. specification of how the __VA_OPT__ construct works in C++20, it is now possible
  399. to have the BOOST_VMD_IS_EMPTY macro work perfectly to test for emptiness
  400. without any of the flaws that exist in the macro for levels of the C++ standard
  401. before C++20. But the macro will only do a 100% reliable test for emptiness
  402. when the compiler is compiling in C++20 mode. For all levels of the C++ standard
  403. before C++20, such as C++98, C++03, C++11, C++14, and C++17, the testing
  404. for emptiness has the corner cases which prevent it from wroking perfectly
  405. which have already been discussed.
  406. </p>
  407. <p>
  408. Furthermore in C++20 mode it is possible that a compiler still does not yet
  409. support the __VA_OPT__ construct, even though it is part of the C++20 standard.
  410. Luckily it is possible to test whether or not a compiler supports the __VA_OPT__
  411. construct in C++20 mode, and the macro implementation of BOOST_VMD_IS_EMPTY
  412. does that before using the construct to provide a perfectly reliable implementation
  413. for testing emptiness.
  414. </p>
  415. <p>
  416. The result of all this is that when a compiler is compiling source using
  417. the C++20 standard, and supports the C++20 __VA_OPT__ preprocessor construct,
  418. the implementation provides a completely reliable way of testing for emptiness
  419. using the BOOST_VMD_IS_EMPTY macro. Otherwise the BOOST_VMD_IS_EMPTY macro
  420. has the corner cases previously discussed which make the macro less than
  421. 100% reliable in testing for emptiness. The good news of course is that more
  422. compilers will be implementaing the C++20 standard and more C++ programmers
  423. will be using the C++20 standard to compile their code.
  424. </p>
  425. <p>
  426. The programmer may know whether the compiler is being used in C++20 mode
  427. from the command line parameters he passes to the compiler, and the programmer
  428. may know whether the compiler in C++20 mode supports the __VA_OPT__ construct
  429. of C++20 from the compiler's documentation. But from the preprocessor programming
  430. perspective it would be good to find out using a macro whether or not C++20
  431. mode with the __VA_OPT__ construct is being used so that the BOOST_VMD_IS_EMPTY
  432. macro can be considered completely reliable in testing for emptiness. Such
  433. a macro does already exist in the Boost Preprocessor library, and it is called
  434. BOOST_PP_VARIADIC_HAS_OPT. You can read the documentation for this macro
  435. in the Boost Preprocessor library documentation, but I will give a quick
  436. rundown of how this works here. The macro is a function-like macro taking
  437. no parameters and returns 1 if the compiler is in C++20 mode and __VA_OPT__
  438. is supported, otherwise returns 0. The header file needed to invoke the macro
  439. as BOOST_PP_VARIADIC_HAS_OPT() is included as:
  440. </p>
  441. <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">variadic</span><span class="special">/</span><span class="identifier">has_opt</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
  442. </pre>
  443. <p>
  444. The programmer does not have to be compiling in C++20 mode to invoke the
  445. BOOST_PP_VARIADIC_HAS_OPT macro. When the programmer is not in C++20 mode
  446. invoking the macro always returns 0. When the programmer is in C++20 mode
  447. invoking the macro returns 1 when the __VA_OPT__ construct is supported and
  448. returns 0 when the __VA_OPT__ construct is not supported. It does this latter
  449. step through clever preprocessor programming.
  450. </p>
  451. <h5>
  452. <a name="variadic_macro_data.vmd_specific.vmd_test_empty.h7"></a>
  453. <span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_test_empty.macro_flaw_conclusion"></a></span><a class="link" href="vmd_specific.html#variadic_macro_data.vmd_specific.vmd_test_empty.macro_flaw_conclusion">Macro
  454. Flaw conclusion</a>
  455. </h5>
  456. <p>
  457. With all of the above mentioned, the cases where BOOST_VMD_IS_EMPTY will
  458. work incorrectly are very small, even with the erroneous VC++ preprocessor,
  459. and I consider the macro worthwhile to use since it works correctly with
  460. the vast majority of possible preprocessor input, and always works correctly
  461. in C++20 mode with __VA_OPT__ preprocessor support.
  462. </p>
  463. <p>
  464. The case where it will not work, with both a C++ standard conforming preprocessor
  465. or with Visual C++, occurs when the name of a function-like macro is part
  466. of the input to BOOST_VMD_IS_EMPTY. Obviously the macro should be used by
  467. the preprocessor metaprogrammer when the possible input to it is constrained
  468. to eliminate the erroneous case.
  469. </p>
  470. <p>
  471. Furthermore, since emptiness can correctly be tested for in nearly every
  472. situation, the BOOST_VMD_IS_EMPTY macro can be used internally when the preprocessor
  473. metaprogrammer wants to return data from a macro and all or part of that
  474. data could be empty.
  475. </p>
  476. <p>
  477. Therefore I believe the BOOST_VMD_IS_EMPTY macro is quite useful, despite
  478. the corner case flaws which makes it imperfect. Consequently I believe that
  479. the preprocessor metaprogrammer can use the concept of empty preprocessor
  480. data in the design of his own macros.
  481. </p>
  482. <h5>
  483. <a name="variadic_macro_data.vmd_specific.vmd_test_empty.h8"></a>
  484. <span class="phrase"><a name="variadic_macro_data.vmd_specific.vmd_test_empty.using_the_macro"></a></span><a class="link" href="vmd_specific.html#variadic_macro_data.vmd_specific.vmd_test_empty.using_the_macro">Using
  485. the macro</a>
  486. </h5>
  487. <p>
  488. The macro BOOST_VMD_IS_EMPTY is used internally throughout VMD and macro
  489. programmers may find this macro useful in their own programming efforts despite
  490. the slight flaw in the way that it works in pre C++20 mode.
  491. </p>
  492. <p>
  493. You can use the general header file:
  494. </p>
  495. <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>
  496. </pre>
  497. <p>
  498. or you can use the individual header file:
  499. </p>
  500. <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">is_empty</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
  501. </pre>
  502. <p>
  503. for the BOOST_VMD_IS_EMPTY macro.
  504. </p>
  505. </div>
  506. <div class="footnotes">
  507. <br><hr style="width:100; text-align:left;margin-left: 0">
  508. <div id="ftn.variadic_macro_data.vmd_specific.vmd_test_empty.f0" class="footnote"><p><a href="#variadic_macro_data.vmd_specific.vmd_test_empty.f0" class="para"><sup class="para">[1] </sup></a>
  509. For VC++ 8 the input is not variadic data but a single parameter
  510. </p></div>
  511. </div>
  512. </div>
  513. <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
  514. <td align="left"></td>
  515. <td align="right"><div class="copyright-footer">Copyright &#169; 2010-2017 Tropic Software
  516. East Inc</div></td>
  517. </tr></table>
  518. <hr>
  519. <div class="spirit-nav">
  520. <a accesskey="p" href="vmd_data_types.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_specific/vmd_constraints.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
  521. </div>
  522. </body>
  523. </html>