vmd_identity.qbk 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. [/
  2. (C) Copyright Edward Diener 2011-2015
  3. Distributed under the Boost Software License, Version 1.0.
  4. (See accompanying file LICENSE_1_0.txt or copy at
  5. http://www.boost.org/LICENSE_1_0.txt).
  6. ]
  7. [section:vmd_identity Generating emptiness and identity]
  8. [heading Using BOOST_PP_EMPTY and BOOST_PP_IDENTITY]
  9. Boost PP Has a macro called BOOST_PP_EMPTY() which expands to nothing.
  10. Ordinarily this would not seem that useful, but the macro can be used
  11. in situations where one wants to return a specific value even though
  12. a further macro call syntax is required taking no parameters.
  13. This sort of usefulness occurs in Boost PP when there are two paths to take depending
  14. on the outcome of a BOOST_PP_IF or BOOST_PP_IIF logic. Here is an artificial example:
  15. #include <boost/preprocessor/control/iif.hpp>
  16. #include <boost/preprocessor/facilities/empty.hpp>
  17. #define MACRO_CHOICE(parameter) \
  18. BOOST_PP_IIF(parameter) \
  19. ( \
  20. MACRO_CALL_IF_PARAMETER_1, \
  21. SOME_FIXED_VALUE BOOST_PP_EMPTY \
  22. ) \
  23. ()
  24. #define MACRO_CALL_IF_PARAMETER_1() some_processing
  25. In the general logic above is: if parameter is 1 another
  26. macro is invoked, whereas if the parameter is 0 some
  27. fixed value is returned. The reason that this is useful
  28. is that one may not want to code the MACRO_CHOICE macro
  29. in this way:
  30. #include <boost/preprocessor/control/iif.hpp>
  31. #define MACRO_CHOICE(parameter) \
  32. BOOST_PP_IIF(parameter) \
  33. ( \
  34. MACRO_CALL_IF_PARAMETER_1(), \
  35. SOME_FIXED_VALUE \
  36. )
  37. #define MACRO_CALL_IF_PARAMETER_1() some_processing
  38. because it is inefficient. The invocation of MACRO_CALL_IF_PARAMETER_1 will still
  39. be generated even when 'parameter' is 0.
  40. This idiom of returning a fixed value through the use of BOOST_PP_EMPTY
  41. is so useful that Boost PP has an accompanying macro to BOOST_PP_EMPTY to
  42. work with it. This accompanying macro is BOOST_PP_IDENTITY(value)().
  43. Essentially BOOST_PP_IDENTITY returns its value when it is invoked.
  44. Again, like BOOST_PP_EMPTY, the final invocation must be done with no value.
  45. Our example from above, which originally used BOOST_PP_EMPTY to return
  46. a fixed value, is now:
  47. #include <boost/preprocessor/control/iif.hpp>
  48. #include <boost/preprocessor/facilities/identity.hpp>
  49. #define MACRO_CHOICE(parameter) \
  50. BOOST_PP_IIF(parameter) \
  51. ( \
  52. MACRO_CALL_IF_PARAMETER_1, \
  53. BOOST_PP_IDENTITY(SOME_FIXED_VALUE) \
  54. ) \
  55. ()
  56. #define MACRO_CALL_IF_PARAMETER_1() some_processing
  57. The macro BOOST_PP_IDENTITY is actually just:
  58. #define BOOST_PP_IDENTITY(value) value BOOST_PP_EMPTY
  59. so you can see how it is essentially a shorthand for the common
  60. case originally shown at the top of returning a value through the
  61. use of BOOST_PP_EMPTY.
  62. [heading Using BOOST_VMD_EMPTY and BOOST_VMD_IDENTITY]
  63. The one problem when using BOOST_PP_EMPTY and BOOST_PP_IDENTITY
  64. is that the final invocation must be with no parameters. This is
  65. very limiting. If the final invocation must be with one or more parameters
  66. you cannot use BOOST_PP_EMPTY or BOOST_PP_IDENTITY. In other words,
  67. making a change to either of our two examples:
  68. #include <boost/preprocessor/control/iif.hpp>
  69. #include <boost/preprocessor/facilities/empty.hpp>
  70. #define MACRO_CHOICE(parameter1,parameter2) \
  71. BOOST_PP_IIF(parameter1) \
  72. ( \
  73. MACRO_CALL_IF_PARAMETER_1, \
  74. SOME_FIXED_VALUE BOOST_PP_EMPTY \
  75. ) \
  76. (parameter2)
  77. #define MACRO_CALL_IF_PARAMETER_1(parameter2) some_processing_using_a_parameter
  78. or
  79. #include <boost/preprocessor/control/iif.hpp>
  80. #include <boost/preprocessor/facilities/identity.hpp>
  81. #define MACRO_CHOICE(parameter1,parameter2) \
  82. BOOST_PP_IIF(parameter1) \
  83. ( \
  84. MACRO_CALL_IF_PARAMETER_1, \
  85. BOOST_PP_IDENTITY(SOME_FIXED_VALUE) \
  86. ) \
  87. (parameter2)
  88. #define MACRO_CALL_IF_PARAMETER_1(parameter2) some_processing_using_a_parameter
  89. will produce a preprocessing error since the final invocation to either
  90. BOOST_PP_EMPTY or BOOST_PP_IDENTITY can not be done with 1 or more parameters.
  91. It would be much more useful if the final invocation could be done with
  92. any number of parameters. This is where using variadic macros solves the problem.
  93. The BOOST_VMD_EMPTY and BOOST_VMD_IDENTITY macros have the exact same
  94. functionality as their Boost PP counterparts but the final invocation can
  95. be made with any number of parameters, and those parameters are just ignored
  96. when BOOST_VMD_EMPTY or BOOST_VMD_IDENTITY is the choice.
  97. Now for our two examples we can have:
  98. #include <boost/preprocessor/control/iif.hpp>
  99. #include <boost/vmd/empty.hpp>
  100. #define MACRO_CHOICE(parameter1,parameter2) \
  101. BOOST_PP_IIF(parameter1) \
  102. ( \
  103. MACRO_CALL_IF_PARAMETER_1, \
  104. SOME_FIXED_VALUE BOOST_VMD_EMPTY \
  105. ) \
  106. (parameter2)
  107. #define MACRO_CALL_IF_PARAMETER_1(parameter2) some_processing_using_parameters
  108. or
  109. #include <boost/preprocessor/control/iif.hpp>
  110. #include <boost/vmd/identity.hpp>
  111. #define MACRO_CHOICE(parameter1,parameter2) \
  112. BOOST_PP_IIF(parameter1) \
  113. ( \
  114. MACRO_CALL_IF_PARAMETER_1, \
  115. BOOST_VMD_IDENTITY(SOME_FIXED_VALUE) \
  116. ) \
  117. (parameter2)
  118. #define MACRO_CALL_IF_PARAMETER_1(parameter2) some_processing_using_parameters
  119. and our macros will compile without preprocessing errors and work as expected.
  120. Both BOOST_VMD_EMPTY and BOOST_VMD_IDENTITY will take any number of parameters
  121. in their invocation, which makes them useful for a final invocation no matter
  122. what is being passed.
  123. [heading Usage for BOOST_VMD_EMPTY and BOOST_VMD_IDENTITY]
  124. To use the BOOST_VMD_EMPTY macro either include the general header:
  125. #include <boost/vmd/vmd.hpp>
  126. or include the specific header:
  127. #include <boost/vmd/empty.hpp>
  128. To use the BOOST_VMD_IDENTITY macro either include the general header:
  129. #include <boost/vmd/vmd.hpp>
  130. or include the specific header:
  131. #include <boost/vmd/identity.hpp>
  132. [heading Using BOOST_VMD_EMPTY and BOOST_VMD_IDENTITY with VC++]
  133. Unfortunately the Visual C++ preprocessor has a problem when a macro
  134. expands to something followed by a variadic macro which expands to nothing.
  135. This is the case when using BOOST_VMD_EMPTY following some non-empty expansion,
  136. or the equivalent use of BOOST_VMD_IDENTITY. As strange as it sounds this VC++
  137. preprocessor problem is normally solved by concatenating the result using BOOST_PP_CAT
  138. with an empty value. But then again the many non-standard behaviors of VC++
  139. are difficult to understand or even track.
  140. In order to make this technique transparent when used with a C++ standard
  141. conforming preprocessor or VC++ non-standard preprocessor you can use the
  142. BOOST_VMD_IDENTITY_RESULT macro passing to it a single parameter which is a result
  143. returned from a macro which uses BOOST_VMD_IDENTITY ( or its equivalent
  144. 'value BOOST_VMD_EMPTY' usage ).
  145. Given our MACRO_CHOICE example above, if you have another macro invoking MACRO_CHOICE
  146. simply enclose that invocation within BOOST_VMD_IDENTITY_RESULT. As in the very simple:
  147. #include <boost/vmd/identity.hpp>
  148. #define CALLING_MACRO_CHOICE(parameter1,parameter2) \
  149. BOOST_VMD_IDENTITY_RESULT(MACRO_CHOICE(parameter1,parameter2))
  150. Alternatively you can change MACRO_CHOICE so that its implementation
  151. and usage is:
  152. #include <boost/preprocessor/control/iif.hpp>
  153. #include <boost/vmd/identity.hpp>
  154. #define MACRO_CHOICE(parameter1,parameter2) \
  155. BOOST_VMD_IDENTITY_RESULT \
  156. ( \
  157. BOOST_PP_IIF(parameter1) \
  158. ( \
  159. MACRO_CALL_IF_PARAMETER_1, \
  160. BOOST_VMD_IDENTITY(SOME_FIXED_VALUE) \
  161. ) \
  162. (parameter2) \
  163. )
  164. #define CALLING_MACRO_CHOICE(parameter1,parameter2) \
  165. MACRO_CHOICE(parameter1,parameter2)
  166. Using BOOST_VMD_EMPTY and BOOST_VMD_IDENTITY in this way will ensure they can be used
  167. without preprocessing problems with either VC++ or any C++ standard conforming preprocessor.
  168. [heading Usage for BOOST_VMD_IDENTITY_RESULT]
  169. The macro BOOST_VMD_IDENTITY_RESULT is in the same header file as BOOST_VMD_IDENTITY,
  170. so to use the BOOST_VMD_IDENTITY_RESULT macro either include the general header:
  171. #include <boost/vmd/vmd.hpp>
  172. or include the specific header:
  173. #include <boost/vmd/identity.hpp>
  174. [endsect]