combine_policies.hpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. // Copyright (c) 2001-2012 Hartmut Kaiser
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #if !defined(BOOST_SPIRIT_ITERATOR_COMBINE_POLICIES_APR_06_2008_0136PM)
  6. #define BOOST_SPIRIT_ITERATOR_COMBINE_POLICIES_APR_06_2008_0136PM
  7. #include <boost/config.hpp>
  8. #include <boost/type_traits/is_empty.hpp>
  9. namespace boost { namespace spirit { namespace iterator_policies
  10. {
  11. ///////////////////////////////////////////////////////////////////////////
  12. // The purpose of the multi_pass_unique template is to eliminate
  13. // empty policy classes (policies not containing any data items) from the
  14. // multiple inheritance chain. This is necessary since some compilers
  15. // fail to apply the empty base optimization if multiple inheritance is
  16. // involved.
  17. // Additionally this can be used to combine separate policies into one
  18. // single multi_pass_policy as required by the multi_pass template
  19. ///////////////////////////////////////////////////////////////////////////
  20. ///////////////////////////////////////////////////////////////////////////
  21. // select the correct derived classes based on if a policy is empty
  22. template <typename T
  23. , typename Ownership, typename Checking, typename Input, typename Storage
  24. , bool OwnershipIsEmpty = boost::is_empty<Ownership>::value
  25. , bool CheckingIsEmpty = boost::is_empty<Checking>::value
  26. , bool InputIsEmpty = boost::is_empty<Input>::value>
  27. struct multi_pass_unique;
  28. ///////////////////////////////////////////////////////////////////////////
  29. template <typename T, typename Ownership, typename Checking
  30. , typename Input, typename Storage>
  31. struct multi_pass_unique<T, Ownership, Checking, Input, Storage
  32. , false, false, false>
  33. : Ownership, Checking, Input, Storage
  34. {
  35. multi_pass_unique() {}
  36. multi_pass_unique(T& x) : Input(x) {}
  37. multi_pass_unique(T const& x) : Input(x) {}
  38. template <typename MultiPass>
  39. static void destroy(MultiPass& mp)
  40. {
  41. Ownership::destroy(mp);
  42. Checking::destroy(mp);
  43. Input::destroy(mp);
  44. Storage::destroy(mp);
  45. }
  46. void swap(multi_pass_unique& x)
  47. {
  48. this->Ownership::swap(x);
  49. this->Checking::swap(x);
  50. this->Input::swap(x);
  51. this->Storage::swap(x);
  52. }
  53. template <typename MultiPass>
  54. inline static void clear_queue(MultiPass& mp)
  55. {
  56. Checking::clear_queue(mp);
  57. Storage::clear_queue(mp);
  58. }
  59. };
  60. ///////////////////////////////////////////////////////////////////////////
  61. template <typename T, typename Ownership, typename Checking
  62. , typename Input, typename Storage>
  63. struct multi_pass_unique<T, Ownership, Checking, Input, Storage
  64. , false, false, true>
  65. : Ownership, Checking, Storage
  66. {
  67. multi_pass_unique() {}
  68. multi_pass_unique(T const&) {}
  69. template <typename MultiPass>
  70. static void destroy(MultiPass& mp)
  71. {
  72. Ownership::destroy(mp);
  73. Checking::destroy(mp);
  74. Input::destroy(mp);
  75. Storage::destroy(mp);
  76. }
  77. void swap(multi_pass_unique& x)
  78. {
  79. this->Ownership::swap(x);
  80. this->Checking::swap(x);
  81. this->Storage::swap(x);
  82. }
  83. template <typename MultiPass>
  84. inline static void clear_queue(MultiPass& mp)
  85. {
  86. Checking::clear_queue(mp);
  87. Storage::clear_queue(mp);
  88. }
  89. // implement input policy functions by forwarding to the Input type
  90. template <typename MultiPass>
  91. inline static void advance_input(MultiPass& mp)
  92. { Input::advance_input(mp); }
  93. template <typename MultiPass>
  94. inline static typename MultiPass::reference get_input(MultiPass& mp)
  95. { return Input::get_input(mp); }
  96. template <typename MultiPass>
  97. inline static bool input_at_eof(MultiPass const& mp)
  98. { return Input::input_at_eof(mp); }
  99. template <typename MultiPass, typename TokenType>
  100. inline static bool input_is_valid(MultiPass& mp, TokenType& curtok)
  101. { return Input::input_is_valid(mp, curtok); }
  102. };
  103. ///////////////////////////////////////////////////////////////////////////
  104. template <typename T, typename Ownership, typename Checking
  105. , typename Input, typename Storage>
  106. struct multi_pass_unique<T, Ownership, Checking, Input, Storage
  107. , false, true, false>
  108. : Ownership, Input, Storage
  109. {
  110. multi_pass_unique() {}
  111. multi_pass_unique(T& x) : Input(x) {}
  112. multi_pass_unique(T const& x) : Input(x) {}
  113. template <typename MultiPass>
  114. static void destroy(MultiPass& mp)
  115. {
  116. Ownership::destroy(mp);
  117. Input::destroy(mp);
  118. Storage::destroy(mp);
  119. }
  120. void swap(multi_pass_unique& x)
  121. {
  122. this->Ownership::swap(x);
  123. this->Input::swap(x);
  124. this->Storage::swap(x);
  125. }
  126. template <typename MultiPass>
  127. inline static void clear_queue(MultiPass& mp)
  128. {
  129. Checking::clear_queue(mp);
  130. Storage::clear_queue(mp);
  131. }
  132. // checking policy functions are forwarded to the Checking type
  133. template <typename MultiPass>
  134. inline static void docheck(MultiPass const& mp)
  135. { Checking::docheck(mp); }
  136. };
  137. ///////////////////////////////////////////////////////////////////////////
  138. template <typename T, typename Ownership, typename Checking
  139. , typename Input, typename Storage>
  140. struct multi_pass_unique<T, Ownership, Checking, Input, Storage
  141. , false, true, true>
  142. : Ownership, Storage
  143. {
  144. multi_pass_unique() {}
  145. multi_pass_unique(T const&) {}
  146. template <typename MultiPass>
  147. static void destroy(MultiPass& mp)
  148. {
  149. Ownership::destroy(mp);
  150. Input::destroy(mp);
  151. Storage::destroy(mp);
  152. }
  153. void swap(multi_pass_unique& x)
  154. {
  155. this->Ownership::swap(x);
  156. this->Storage::swap(x);
  157. }
  158. template <typename MultiPass>
  159. inline static void clear_queue(MultiPass& mp)
  160. {
  161. Checking::clear_queue(mp);
  162. Storage::clear_queue(mp);
  163. }
  164. // implement input policy functions by forwarding to the Input type
  165. template <typename MultiPass>
  166. inline static void advance_input(MultiPass& mp)
  167. { Input::advance_input(mp); }
  168. template <typename MultiPass>
  169. inline static typename MultiPass::reference get_input(MultiPass& mp)
  170. { return Input::get_input(mp); }
  171. template <typename MultiPass>
  172. inline static bool input_at_eof(MultiPass const& mp)
  173. { return Input::input_at_eof(mp); }
  174. template <typename MultiPass, typename TokenType>
  175. inline static bool input_is_valid(MultiPass& mp, TokenType& curtok)
  176. { return Input::input_is_valid(mp, curtok); }
  177. // checking policy functions are forwarded to the Checking type
  178. template <typename MultiPass>
  179. inline static void docheck(MultiPass const& mp)
  180. { Checking::docheck(mp); }
  181. };
  182. ///////////////////////////////////////////////////////////////////////////
  183. template <typename T, typename Ownership, typename Checking
  184. , typename Input, typename Storage>
  185. struct multi_pass_unique<T, Ownership, Checking, Input, Storage
  186. , true, false, false>
  187. : Checking, Input, Storage
  188. {
  189. multi_pass_unique() {}
  190. multi_pass_unique(T& x) : Input(x) {}
  191. multi_pass_unique(T const& x) : Input(x) {}
  192. template <typename MultiPass>
  193. static void destroy(MultiPass& mp)
  194. {
  195. Checking::destroy(mp);
  196. Input::destroy(mp);
  197. Storage::destroy(mp);
  198. }
  199. void swap(multi_pass_unique& x)
  200. {
  201. this->Checking::swap(x);
  202. this->Input::swap(x);
  203. this->Storage::swap(x);
  204. }
  205. template <typename MultiPass>
  206. inline static void clear_queue(MultiPass& mp)
  207. {
  208. Checking::clear_queue(mp);
  209. Storage::clear_queue(mp);
  210. }
  211. // ownership policy functions are forwarded to the Ownership type
  212. template <typename MultiPass>
  213. inline static void clone(MultiPass& mp)
  214. { Ownership::clone(mp); }
  215. template <typename MultiPass>
  216. inline static bool release(MultiPass& mp)
  217. { return Ownership::release(mp); }
  218. template <typename MultiPass>
  219. inline static bool is_unique(MultiPass const& mp)
  220. { return Ownership::is_unique(mp); }
  221. };
  222. ///////////////////////////////////////////////////////////////////////////
  223. template <typename T, typename Ownership, typename Checking
  224. , typename Input, typename Storage>
  225. struct multi_pass_unique<T, Ownership, Checking, Input, Storage
  226. , true, false, true>
  227. : Checking, Storage
  228. {
  229. multi_pass_unique() {}
  230. multi_pass_unique(T const&) {}
  231. template <typename MultiPass>
  232. static void destroy(MultiPass& mp)
  233. {
  234. Checking::destroy(mp);
  235. Input::destroy(mp);
  236. Storage::destroy(mp);
  237. }
  238. void swap(multi_pass_unique& x)
  239. {
  240. this->Checking::swap(x);
  241. this->Storage::swap(x);
  242. }
  243. template <typename MultiPass>
  244. inline static void clear_queue(MultiPass& mp)
  245. {
  246. Checking::clear_queue(mp);
  247. Storage::clear_queue(mp);
  248. }
  249. // implement input policy functions by forwarding to the Input type
  250. template <typename MultiPass>
  251. inline static void advance_input(MultiPass& mp)
  252. { Input::advance_input(mp); }
  253. template <typename MultiPass>
  254. inline static typename MultiPass::reference get_input(MultiPass& mp)
  255. { return Input::get_input(mp); }
  256. template <typename MultiPass>
  257. inline static bool input_at_eof(MultiPass const& mp)
  258. { return Input::input_at_eof(mp); }
  259. template <typename MultiPass, typename TokenType>
  260. inline static bool input_is_valid(MultiPass& mp, TokenType& curtok)
  261. { return Input::input_is_valid(mp, curtok); }
  262. // ownership policy functions are forwarded to the Ownership type
  263. template <typename MultiPass>
  264. inline static void clone(MultiPass& mp)
  265. { Ownership::clone(mp); }
  266. template <typename MultiPass>
  267. inline static bool release(MultiPass& mp)
  268. { return Ownership::release(mp); }
  269. template <typename MultiPass>
  270. inline static bool is_unique(MultiPass const& mp)
  271. { return Ownership::is_unique(mp); }
  272. };
  273. ///////////////////////////////////////////////////////////////////////////
  274. template <typename T, typename Ownership, typename Checking
  275. , typename Input, typename Storage>
  276. struct multi_pass_unique<T, Ownership, Checking, Input, Storage
  277. , true, true, false>
  278. : Input, Storage
  279. {
  280. multi_pass_unique() {}
  281. multi_pass_unique(T& x) : Input(x) {}
  282. multi_pass_unique(T const& x) : Input(x) {}
  283. template <typename MultiPass>
  284. static void destroy(MultiPass& mp)
  285. {
  286. Input::destroy(mp);
  287. Storage::destroy(mp);
  288. }
  289. void swap(multi_pass_unique& x)
  290. {
  291. this->Input::swap(x);
  292. this->Storage::swap(x);
  293. }
  294. template <typename MultiPass>
  295. inline static void clear_queue(MultiPass& mp)
  296. {
  297. Checking::clear_queue(mp);
  298. Storage::clear_queue(mp);
  299. }
  300. // checking policy functions are forwarded to the Checking type
  301. template <typename MultiPass>
  302. inline static void docheck(MultiPass const& mp)
  303. { Checking::docheck(mp); }
  304. // ownership policy functions are forwarded to the Ownership type
  305. template <typename MultiPass>
  306. inline static void clone(MultiPass& mp)
  307. { Ownership::clone(mp); }
  308. template <typename MultiPass>
  309. inline static bool release(MultiPass& mp)
  310. { return Ownership::release(mp); }
  311. template <typename MultiPass>
  312. inline static bool is_unique(MultiPass const& mp)
  313. { return Ownership::is_unique(mp); }
  314. };
  315. ///////////////////////////////////////////////////////////////////////////
  316. template <typename T, typename Ownership, typename Checking
  317. , typename Input, typename Storage>
  318. struct multi_pass_unique<T, Ownership, Checking, Input, Storage
  319. , true, true, true>
  320. : Storage
  321. {
  322. multi_pass_unique() {}
  323. multi_pass_unique(T const&) {}
  324. template <typename MultiPass>
  325. static void destroy(MultiPass& mp)
  326. {
  327. Input::destroy(mp);
  328. Storage::destroy(mp);
  329. }
  330. void swap(multi_pass_unique& x)
  331. {
  332. this->Storage::swap(x);
  333. }
  334. template <typename MultiPass>
  335. inline static void clear_queue(MultiPass& mp)
  336. {
  337. Checking::clear_queue(mp);
  338. Storage::clear_queue(mp);
  339. }
  340. // implement input policy functions by forwarding to the Input type
  341. template <typename MultiPass>
  342. inline static void advance_input(MultiPass& mp)
  343. { Input::advance_input(mp); }
  344. template <typename MultiPass>
  345. inline static typename MultiPass::reference get_input(MultiPass& mp)
  346. { return Input::get_input(mp); }
  347. template <typename MultiPass>
  348. inline static bool input_at_eof(MultiPass const& mp)
  349. { return Input::input_at_eof(mp); }
  350. template <typename MultiPass, typename TokenType>
  351. inline static bool input_is_valid(MultiPass& mp, TokenType& curtok)
  352. { return Input::input_is_valid(mp, curtok); }
  353. // checking policy functions are forwarded to the Checking type
  354. template <typename MultiPass>
  355. inline static void docheck(MultiPass const& mp)
  356. { Checking::docheck(mp); }
  357. // ownership policy functions are forwarded to the Ownership type
  358. template <typename MultiPass>
  359. inline static void clone(MultiPass& mp)
  360. { Ownership::clone(mp); }
  361. template <typename MultiPass>
  362. inline static bool release(MultiPass& mp)
  363. { return Ownership::release(mp); }
  364. template <typename MultiPass>
  365. inline static bool is_unique(MultiPass const& mp)
  366. { return Ownership::is_unique(mp); }
  367. };
  368. ///////////////////////////////////////////////////////////////////////////
  369. // the multi_pass_shared structure is used to combine the shared data items
  370. // of all policies into one single structure
  371. ///////////////////////////////////////////////////////////////////////////
  372. template<typename T, typename Ownership, typename Checking, typename Input
  373. , typename Storage>
  374. struct multi_pass_shared : Ownership, Checking, Input, Storage
  375. {
  376. explicit multi_pass_shared(T& input) : Input(input) {}
  377. explicit multi_pass_shared(T const& input) : Input(input) {}
  378. };
  379. ///////////////////////////////////////////////////////////////////////////
  380. // This is a default implementation of a policy class as required by the
  381. // multi_pass template, combining 4 separate policies into one. Any other
  382. // multi_pass policy class needs to follow the scheme as shown below.
  383. template<typename Ownership, typename Checking, typename Input
  384. , typename Storage>
  385. struct default_policy
  386. {
  387. typedef Ownership ownership_policy;
  388. typedef Checking checking_policy;
  389. typedef Input input_policy;
  390. typedef Storage storage_policy;
  391. ///////////////////////////////////////////////////////////////////////
  392. template <typename T>
  393. struct unique : multi_pass_unique<T
  394. , typename Ownership::unique, typename Checking::unique
  395. , typename Input::BOOST_NESTED_TEMPLATE unique<T>
  396. , typename Storage::BOOST_NESTED_TEMPLATE unique<
  397. typename Input::BOOST_NESTED_TEMPLATE unique<T>::value_type> >
  398. {
  399. typedef typename Ownership::unique ownership_policy;
  400. typedef typename Checking::unique checking_policy;
  401. typedef typename Input::BOOST_NESTED_TEMPLATE unique<T>
  402. input_policy;
  403. typedef typename Storage::BOOST_NESTED_TEMPLATE unique<
  404. typename input_policy::value_type> storage_policy;
  405. typedef multi_pass_unique<T, ownership_policy, checking_policy
  406. , input_policy, storage_policy> unique_base_type;
  407. unique() {}
  408. explicit unique(T& input) : unique_base_type(input) {}
  409. explicit unique(T const& input) : unique_base_type(input) {}
  410. };
  411. ///////////////////////////////////////////////////////////////////////
  412. template <typename T>
  413. struct shared : multi_pass_shared<T
  414. , typename Ownership::shared, typename Checking::shared
  415. , typename Input::BOOST_NESTED_TEMPLATE shared<T>
  416. , typename Storage::BOOST_NESTED_TEMPLATE shared<
  417. typename Input::BOOST_NESTED_TEMPLATE unique<T>::value_type> >
  418. {
  419. typedef typename Ownership::shared ownership_policy;
  420. typedef typename Checking::shared checking_policy;
  421. typedef typename Input::BOOST_NESTED_TEMPLATE shared<T>
  422. input_policy;
  423. typedef typename Storage::BOOST_NESTED_TEMPLATE shared<
  424. typename Input::BOOST_NESTED_TEMPLATE unique<T>::value_type>
  425. storage_policy;
  426. typedef multi_pass_shared<T, ownership_policy, checking_policy
  427. , input_policy, storage_policy> shared_base_type;
  428. explicit shared(T& input)
  429. : shared_base_type(input), inhibit_clear_queue_(false) {}
  430. explicit shared(T const& input)
  431. : shared_base_type(input), inhibit_clear_queue_(false) {}
  432. // This is needed for the correct implementation of expectation
  433. // points. Normally expectation points flush any multi_pass
  434. // iterator they may act on, but if the corresponding error handler
  435. // is of type 'retry' no flushing of the internal buffers should be
  436. // executed (even if explicitly requested).
  437. bool inhibit_clear_queue_;
  438. };
  439. };
  440. }}}
  441. #endif