test_doc_example_switch.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  1. // (C) Copyright Edward Diener 2011-2015
  2. // Use, modification and distribution are subject to the Boost Software License,
  3. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt).
  5. #if !defined(BOOST_VMD_TEST_DOC_EXAMPLE_SWITCH_HPP)
  6. #define BOOST_VMD_TEST_DOC_EXAMPLE_SWITCH_HPP
  7. //[ example_switch
  8. #include <boost/vmd/detail/setup.hpp>
  9. #if BOOST_PP_VARIADICS
  10. #include <boost/preprocessor/cat.hpp>
  11. #include <boost/preprocessor/arithmetic/inc.hpp>
  12. #include <boost/preprocessor/comparison/equal.hpp>
  13. #include <boost/preprocessor/control/expr_iif.hpp>
  14. #include <boost/preprocessor/control/iif.hpp>
  15. #include <boost/preprocessor/control/while.hpp>
  16. #include <boost/preprocessor/tuple/elem.hpp>
  17. #include <boost/preprocessor/tuple/enum.hpp>
  18. #include <boost/preprocessor/facilities/expand.hpp>
  19. #include <boost/preprocessor/tuple/replace.hpp>
  20. #include <boost/preprocessor/tuple/size.hpp>
  21. #include <boost/preprocessor/variadic/to_tuple.hpp>
  22. #include <boost/preprocessor/variadic/size.hpp>
  23. #include <boost/vmd/equal.hpp>
  24. #include <boost/vmd/identity.hpp>
  25. #include <boost/vmd/is_empty.hpp>
  26. /*
  27. State index into state values
  28. */
  29. #define BOOST_VMD_SWITCH_STATE_ELEM_INDEX 2
  30. #define BOOST_VMD_SWITCH_STATE_ELEM_DEFAULT 4
  31. #define BOOST_VMD_SWITCH_STATE_ELEM_RESULT 5
  32. /*
  33. Retrieve the state value, never changes
  34. */
  35. #define BOOST_VMD_SWITCH_STATE_GET_VALUE(state) \
  36. BOOST_PP_TUPLE_ELEM(0,state) \
  37. /**/
  38. /*
  39. Retrieve the state tuple of values, never changes
  40. */
  41. #define BOOST_VMD_SWITCH_STATE_GET_CHOICES(state) \
  42. BOOST_PP_TUPLE_ELEM(1,state) \
  43. /**/
  44. /*
  45. Retrieve the state index
  46. */
  47. #define BOOST_VMD_SWITCH_STATE_GET_INDEX(state) \
  48. BOOST_PP_TUPLE_ELEM(2,state) \
  49. /**/
  50. /*
  51. Retrieve the state tuple of values size, never changes
  52. */
  53. #define BOOST_VMD_SWITCH_STATE_GET_SIZE(state) \
  54. BOOST_PP_TUPLE_ELEM(3,state) \
  55. /**/
  56. /*
  57. Retrieve the state default tuple
  58. */
  59. #define BOOST_VMD_SWITCH_STATE_GET_DEFAULT(state) \
  60. BOOST_PP_TUPLE_ELEM(4,state) \
  61. /**/
  62. /*
  63. Retrieve the state result tuple
  64. */
  65. #define BOOST_VMD_SWITCH_STATE_GET_RESULT(state) \
  66. BOOST_PP_TUPLE_ELEM(5,state) \
  67. /**/
  68. /*
  69. Retrieve the current value tuple
  70. */
  71. #define BOOST_VMD_SWITCH_STATE_GET_CURRENT_CHOICE(state) \
  72. BOOST_PP_TUPLE_ELEM \
  73. ( \
  74. BOOST_VMD_SWITCH_STATE_GET_INDEX(state), \
  75. BOOST_VMD_SWITCH_STATE_GET_CHOICES(state) \
  76. ) \
  77. /**/
  78. /*
  79. Expands to the state
  80. value = value to compare against
  81. tuple = choices as a tuple of values
  82. size = size of tuple of values
  83. None of these ever change in the WHILE state
  84. */
  85. #define BOOST_VMD_SWITCH_STATE_EXPAND(value,tuple,size) \
  86. (value,tuple,0,size,(0,),(,)) \
  87. /**/
  88. /*
  89. Expands to the WHILE state
  90. The state to our WHILE consists of a tuple of elements:
  91. 1: value to compare against
  92. 2: tuple of values. Each value is a value/macro pair or if the default just a macro
  93. 3: index into the values
  94. 4: tuple for default macro. 0 means no default macro, 1 means default macro and then second value is the default macro.
  95. 5: tuple of result matched. Emptiness means no result yet specified, 0 means no match, 1 means match and second value is the matching macro.
  96. */
  97. #define BOOST_VMD_SWITCH_STATE(value,...) \
  98. BOOST_VMD_SWITCH_STATE_EXPAND \
  99. ( \
  100. value, \
  101. BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__), \
  102. BOOST_PP_VARIADIC_SIZE(__VA_ARGS__) \
  103. ) \
  104. /**/
  105. /*
  106. Sets the state upon a successful match.
  107. macro = is the matching macro found
  108. */
  109. #define BOOST_VMD_SWITCH_OP_SUCCESS(d,state,macro) \
  110. BOOST_PP_TUPLE_REPLACE_D \
  111. ( \
  112. d, \
  113. state, \
  114. BOOST_VMD_SWITCH_STATE_ELEM_RESULT, \
  115. (1,macro) \
  116. ) \
  117. /**/
  118. /*
  119. Sets the state upon final failure to find a match.
  120. def = default tuple macro, ignored
  121. */
  122. #define BOOST_VMD_SWITCH_OP_FAILURE(d,state,def) \
  123. BOOST_PP_TUPLE_REPLACE_D \
  124. ( \
  125. d, \
  126. state, \
  127. BOOST_VMD_SWITCH_STATE_ELEM_RESULT, \
  128. (0,) \
  129. ) \
  130. /**/
  131. /*
  132. Increments the state index into the tuple values
  133. */
  134. #define BOOST_VMD_SWITCH_OP_UPDATE_INDEX(d,state) \
  135. BOOST_PP_TUPLE_REPLACE_D \
  136. ( \
  137. d, \
  138. state, \
  139. BOOST_VMD_SWITCH_STATE_ELEM_INDEX, \
  140. BOOST_PP_INC(BOOST_VMD_SWITCH_STATE_GET_INDEX(state)) \
  141. ) \
  142. /**/
  143. /*
  144. Choose our current value's macro as our successful match
  145. tuple = current tuple to test
  146. */
  147. #define BOOST_VMD_SWITCH_OP_TEST_CURRENT_VALUE_MATCH(d,state,tuple) \
  148. BOOST_VMD_SWITCH_OP_SUCCESS(d,state,BOOST_PP_TUPLE_ELEM(1,tuple)) \
  149. /**/
  150. /*
  151. Update our state index
  152. tuple = current tuple to test, ignored
  153. */
  154. #define BOOST_VMD_SWITCH_OP_TEST_CURRENT_VALUE_UPDATE_INDEX(d,state,tuple) \
  155. BOOST_VMD_SWITCH_OP_UPDATE_INDEX(d,state) \
  156. /**/
  157. /*
  158. Test our current value against our value to compare against
  159. tuple = current tuple to test
  160. */
  161. #define BOOST_VMD_SWITCH_OP_TEST_CURRENT_VALUE(d,state,tuple) \
  162. BOOST_PP_IIF \
  163. ( \
  164. BOOST_VMD_EQUAL_D \
  165. ( \
  166. d, \
  167. BOOST_VMD_SWITCH_STATE_GET_VALUE(state), \
  168. BOOST_PP_TUPLE_ELEM(0,tuple) \
  169. ), \
  170. BOOST_VMD_SWITCH_OP_TEST_CURRENT_VALUE_MATCH, \
  171. BOOST_VMD_SWITCH_OP_TEST_CURRENT_VALUE_UPDATE_INDEX \
  172. ) \
  173. (d,state,tuple) \
  174. /**/
  175. /*
  176. Set our default macro and update the index in our WHILE state
  177. tuple = current tuple to test
  178. */
  179. #if BOOST_VMD_MSVC
  180. #define BOOST_VMD_SWITCH_OP_TEST_CURRENT_CREATE_DEFAULT_NN(number,name) \
  181. (number,name) \
  182. /**/
  183. #define BOOST_VMD_SWITCH_OP_TEST_CURRENT_CREATE_DEFAULT(d,state,tuple) \
  184. BOOST_VMD_SWITCH_OP_UPDATE_INDEX \
  185. ( \
  186. d, \
  187. BOOST_PP_TUPLE_REPLACE_D \
  188. ( \
  189. d, \
  190. state, \
  191. BOOST_VMD_SWITCH_STATE_ELEM_DEFAULT, \
  192. BOOST_VMD_SWITCH_OP_TEST_CURRENT_CREATE_DEFAULT_NN(1,BOOST_PP_TUPLE_ENUM(tuple)) \
  193. ) \
  194. ) \
  195. /**/
  196. #else
  197. #define BOOST_VMD_SWITCH_OP_TEST_CURRENT_CREATE_DEFAULT(d,state,tuple) \
  198. BOOST_VMD_SWITCH_OP_UPDATE_INDEX \
  199. ( \
  200. d, \
  201. BOOST_PP_TUPLE_REPLACE_D \
  202. ( \
  203. d, \
  204. state, \
  205. BOOST_VMD_SWITCH_STATE_ELEM_DEFAULT, \
  206. (1,BOOST_PP_TUPLE_ENUM(tuple)) \
  207. ) \
  208. ) \
  209. /**/
  210. #endif
  211. /*
  212. If our current value is a default macro, just set the default macro,
  213. else test our current value.
  214. tuple = current tuple to test
  215. */
  216. #define BOOST_VMD_SWITCH_OP_TEST_CURRENT_TUPLE(d,state,tuple) \
  217. BOOST_PP_IIF \
  218. ( \
  219. BOOST_PP_EQUAL_D \
  220. ( \
  221. d, \
  222. BOOST_PP_TUPLE_SIZE(tuple), \
  223. 1 \
  224. ), \
  225. BOOST_VMD_SWITCH_OP_TEST_CURRENT_CREATE_DEFAULT, \
  226. BOOST_VMD_SWITCH_OP_TEST_CURRENT_VALUE \
  227. ) \
  228. (d,state,tuple) \
  229. /**/
  230. /*
  231. Test the current value in our tuple of values
  232. */
  233. #define BOOST_VMD_SWITCH_OP_TEST_CURRENT(d,state) \
  234. BOOST_VMD_SWITCH_OP_TEST_CURRENT_TUPLE \
  235. ( \
  236. d, \
  237. state, \
  238. BOOST_VMD_SWITCH_STATE_GET_CURRENT_CHOICE(state) \
  239. ) \
  240. /**/
  241. /*
  242. Choose the default macro as our successful match
  243. def = default tuple consisting of just the default macro name
  244. */
  245. #define BOOST_VMD_SWITCH_OP_DEFAULT_RET_CHOSEN(d,state,def) \
  246. BOOST_VMD_SWITCH_OP_SUCCESS \
  247. ( \
  248. d, \
  249. state, \
  250. BOOST_PP_TUPLE_ELEM(1,def) \
  251. ) \
  252. /**/
  253. /*
  254. If the default macro exists, choose it else indicate no macro was found
  255. def = default tuple consisting of just the default macro name
  256. */
  257. #define BOOST_VMD_SWITCH_OP_DEFAULT_RET(d,state,def) \
  258. BOOST_PP_IIF \
  259. ( \
  260. BOOST_PP_TUPLE_ELEM(0,def), \
  261. BOOST_VMD_SWITCH_OP_DEFAULT_RET_CHOSEN, \
  262. BOOST_VMD_SWITCH_OP_FAILURE \
  263. ) \
  264. (d,state,def) \
  265. /**/
  266. /*
  267. Try to choose the default macro if it exists
  268. */
  269. #define BOOST_VMD_SWITCH_OP_DEFAULT(d,state) \
  270. BOOST_VMD_SWITCH_OP_DEFAULT_RET \
  271. ( \
  272. d, \
  273. state, \
  274. BOOST_VMD_SWITCH_STATE_GET_DEFAULT(state) \
  275. ) \
  276. /**/
  277. /*
  278. WHILE loop operation
  279. Check for the next value match or try to choose the default if all matches have been checked
  280. */
  281. #define BOOST_VMD_SWITCH_OP(d,state) \
  282. BOOST_PP_IIF \
  283. ( \
  284. BOOST_PP_EQUAL_D \
  285. ( \
  286. d, \
  287. BOOST_VMD_SWITCH_STATE_GET_INDEX(state), \
  288. BOOST_VMD_SWITCH_STATE_GET_SIZE(state) \
  289. ), \
  290. BOOST_VMD_SWITCH_OP_DEFAULT, \
  291. BOOST_VMD_SWITCH_OP_TEST_CURRENT \
  292. ) \
  293. (d,state) \
  294. /**/
  295. /*
  296. WHILE loop predicate
  297. Continue the WHILE loop if a result has not yet been specified
  298. */
  299. #define BOOST_VMD_SWITCH_PRED(d,state) \
  300. BOOST_VMD_IS_EMPTY \
  301. ( \
  302. BOOST_PP_TUPLE_ELEM \
  303. ( \
  304. 0, \
  305. BOOST_VMD_SWITCH_STATE_GET_RESULT(state) \
  306. ) \
  307. ) \
  308. /**/
  309. /*
  310. Invokes the function-like macro
  311. macro = function-like macro name
  312. tparams = tuple of macro parameters
  313. */
  314. #define BOOST_VMD_SWITCH_PROCESS_INVOKE_MACRO(macro,tparams) \
  315. BOOST_PP_EXPAND(macro tparams) \
  316. /**/
  317. /*
  318. Processes our WHILE loop result
  319. callp = tuple of parameters for the called macro
  320. result = tuple. The first tuple element is 0
  321. if no macro has been found or 1 if a macro
  322. has been found. If 1 the second element is
  323. the name of a function-like macro
  324. */
  325. #define BOOST_VMD_SWITCH_PROCESS(callp,result) \
  326. BOOST_PP_EXPR_IIF \
  327. ( \
  328. BOOST_PP_TUPLE_ELEM(0,result), \
  329. BOOST_VMD_SWITCH_PROCESS_INVOKE_MACRO \
  330. ( \
  331. BOOST_PP_TUPLE_ELEM(1,result), \
  332. callp \
  333. ) \
  334. ) \
  335. /**/
  336. /*
  337. Use BOOST_VMD_SWITCH_IDENTITY to pass a fixed value instead
  338. of a function-like macro as the second element of
  339. any tuple of the variadic parameters, or as the default
  340. value, to BOOST_VMD_SWITCH.
  341. */
  342. #if BOOST_VMD_MSVC
  343. #define BOOST_VMD_SWITCH_IDENTITY(item) BOOST_PP_CAT(BOOST_VMD_IDENTITY(item),)
  344. #else
  345. #define BOOST_VMD_SWITCH_IDENTITY BOOST_VMD_IDENTITY
  346. #endif
  347. /*
  348. Switch macro
  349. Parameters are:
  350. value = value to compare against. May be any VMD data value.
  351. callp = tuple of parameters for the called macro
  352. variadic parameters = each parameter must be a tuple.
  353. Each tuple consists of a two-element tuple. The first element is
  354. a value, which may be any VMD data value, and the second element
  355. is the name of a function-like macro to be called if the value
  356. is equal to the value to compare against. For a default value
  357. the tuple is a single-element tuple which contains the name of
  358. a function-like macro to be called if no other value matches.
  359. */
  360. #define BOOST_VMD_SWITCH(value,callp,...) \
  361. BOOST_VMD_SWITCH_PROCESS \
  362. ( \
  363. callp, \
  364. BOOST_VMD_SWITCH_STATE_GET_RESULT \
  365. ( \
  366. BOOST_PP_WHILE \
  367. ( \
  368. BOOST_VMD_SWITCH_PRED, \
  369. BOOST_VMD_SWITCH_OP, \
  370. BOOST_VMD_SWITCH_STATE(value,__VA_ARGS__) \
  371. ) \
  372. ) \
  373. ) \
  374. /**/
  375. #endif /* BOOST_PP_VARIADICS */
  376. //]
  377. #endif /* BOOST_VMD_TEST_DOC_EXAMPLE_SWITCH_HPP */