fusion.hpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720
  1. ///////////////////////////////////////////////////////////////////////////////
  2. /// \file fusion.hpp
  3. /// Make any Proto expression a valid Fusion sequence
  4. //
  5. // Copyright 2008 Eric Niebler. Distributed under the Boost
  6. // Software License, Version 1.0. (See accompanying file
  7. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  8. #ifndef BOOST_PROTO_FUSION_HPP_EAN_11_04_2006
  9. #define BOOST_PROTO_FUSION_HPP_EAN_11_04_2006
  10. #include <boost/config.hpp>
  11. #include <boost/mpl/if.hpp>
  12. #include <boost/mpl/bool.hpp>
  13. #include <boost/mpl/long.hpp>
  14. #include <boost/mpl/sequence_tag_fwd.hpp>
  15. #include <boost/utility/enable_if.hpp>
  16. #include <boost/fusion/include/is_view.hpp>
  17. #include <boost/fusion/include/tag_of_fwd.hpp>
  18. #include <boost/fusion/include/category_of.hpp>
  19. #include <boost/fusion/include/iterator_base.hpp>
  20. #include <boost/fusion/include/intrinsic.hpp>
  21. #include <boost/fusion/include/single_view.hpp>
  22. #include <boost/fusion/include/transform.hpp>
  23. #include <boost/fusion/include/as_list.hpp>
  24. #include <boost/fusion/include/is_segmented.hpp>
  25. #include <boost/fusion/sequence/comparison/enable_comparison.hpp>
  26. #include <boost/proto/proto_fwd.hpp>
  27. #include <boost/proto/traits.hpp>
  28. #include <boost/proto/eval.hpp>
  29. #include <boost/proto/make_expr.hpp>
  30. #ifdef BOOST_MSVC
  31. #pragma warning(push)
  32. #pragma warning(disable : 4510) // default constructor could not be generated
  33. #pragma warning(disable : 4512) // assignment operator could not be generated
  34. #pragma warning(disable : 4610) // can never be instantiated - user defined constructor required
  35. #endif
  36. namespace boost { namespace proto
  37. {
  38. namespace detail
  39. {
  40. template<typename Expr, long Pos>
  41. struct expr_iterator
  42. : fusion::iterator_base<expr_iterator<Expr, Pos> >
  43. {
  44. typedef Expr expr_type;
  45. static const long index = Pos;
  46. typedef fusion::random_access_traversal_tag category;
  47. typedef
  48. tag::proto_expr_iterator<
  49. typename Expr::proto_tag
  50. , typename Expr::proto_domain
  51. >
  52. fusion_tag;
  53. explicit expr_iterator(Expr &e)
  54. : expr(e)
  55. {}
  56. Expr &expr;
  57. };
  58. template<typename Tag>
  59. struct as_element
  60. {
  61. template<typename Sig>
  62. struct result;
  63. template<typename This, typename Expr>
  64. struct result<This(Expr)>
  65. : result<This(Expr const &)>
  66. {};
  67. template<typename This, typename Expr>
  68. struct result<This(Expr &)>
  69. : mpl::if_c<
  70. is_same<Tag, typename Expr::proto_tag>::value
  71. , flat_view<Expr>
  72. , fusion::single_view<Expr &>
  73. >
  74. {};
  75. template<typename Expr>
  76. typename result<as_element(Expr &)>::type const
  77. operator ()(Expr &e) const
  78. {
  79. return typename result<as_element(Expr &)>::type(e);
  80. }
  81. template<typename Expr>
  82. typename result<as_element(Expr const &)>::type const
  83. operator ()(Expr const &e) const
  84. {
  85. return typename result<as_element(Expr const &)>::type(e);
  86. }
  87. };
  88. template<typename Expr>
  89. struct flat_view
  90. : fusion::sequence_base<flat_view<Expr> >
  91. {
  92. typedef fusion::forward_traversal_tag category;
  93. typedef
  94. tag::proto_flat_view<
  95. typename Expr::proto_tag
  96. , typename Expr::proto_domain
  97. >
  98. fusion_tag;
  99. typedef
  100. typename fusion::result_of::as_list<
  101. typename fusion::result_of::transform<
  102. Expr
  103. , as_element<typename Expr::proto_tag>
  104. >::type
  105. >::type
  106. segments_type;
  107. explicit flat_view(Expr &e)
  108. : segs_(fusion::as_list(fusion::transform(e, as_element<typename Expr::proto_tag>())))
  109. {}
  110. segments_type segs_;
  111. };
  112. }
  113. namespace result_of
  114. {
  115. template<typename Expr>
  116. struct flatten
  117. : flatten<Expr const &>
  118. {};
  119. template<typename Expr>
  120. struct flatten<Expr &>
  121. {
  122. typedef detail::flat_view<Expr> type;
  123. };
  124. }
  125. namespace functional
  126. {
  127. /// \brief A PolymorphicFunctionObject type that returns a "flattened"
  128. /// view of a Proto expression tree.
  129. ///
  130. /// A PolymorphicFunctionObject type that returns a "flattened"
  131. /// view of a Proto expression tree. For a tree with a top-most node
  132. /// tag of type \c T, the elements of the flattened sequence are
  133. /// determined by recursing into each child node with the same
  134. /// tag type and returning those nodes of different type. So for
  135. /// instance, the Proto expression tree corresponding to the
  136. /// expression <tt>a | b | c</tt> has a flattened view with elements
  137. /// [a, b, c], even though the tree is grouped as
  138. /// <tt>((a | b) | c)</tt>.
  139. struct flatten
  140. {
  141. BOOST_PROTO_CALLABLE()
  142. template<typename Sig>
  143. struct result;
  144. template<typename This, typename Expr>
  145. struct result<This(Expr)>
  146. : result<This(Expr const &)>
  147. {};
  148. template<typename This, typename Expr>
  149. struct result<This(Expr &)>
  150. {
  151. typedef proto::detail::flat_view<Expr> type;
  152. };
  153. template<typename Expr>
  154. proto::detail::flat_view<Expr> const
  155. operator ()(Expr &e) const
  156. {
  157. return proto::detail::flat_view<Expr>(e);
  158. }
  159. template<typename Expr>
  160. proto::detail::flat_view<Expr const> const
  161. operator ()(Expr const &e) const
  162. {
  163. return proto::detail::flat_view<Expr const>(e);
  164. }
  165. };
  166. }
  167. /// \brief A function that returns a "flattened"
  168. /// view of a Proto expression tree.
  169. ///
  170. /// For a tree with a top-most node
  171. /// tag of type \c T, the elements of the flattened sequence are
  172. /// determined by recursing into each child node with the same
  173. /// tag type and returning those nodes of different type. So for
  174. /// instance, the Proto expression tree corresponding to the
  175. /// expression <tt>a | b | c</tt> has a flattened view with elements
  176. /// [a, b, c], even though the tree is grouped as
  177. /// <tt>((a | b) | c)</tt>.
  178. template<typename Expr>
  179. proto::detail::flat_view<Expr> const
  180. flatten(Expr &e)
  181. {
  182. return proto::detail::flat_view<Expr>(e);
  183. }
  184. /// \overload
  185. ///
  186. template<typename Expr>
  187. proto::detail::flat_view<Expr const> const
  188. flatten(Expr const &e)
  189. {
  190. return proto::detail::flat_view<Expr const>(e);
  191. }
  192. /// INTERNAL ONLY
  193. ///
  194. template<typename Context>
  195. struct eval_fun
  196. : proto::callable
  197. {
  198. explicit eval_fun(Context &ctx)
  199. : ctx_(ctx)
  200. {}
  201. template<typename Sig>
  202. struct result;
  203. template<typename This, typename Expr>
  204. struct result<This(Expr)>
  205. : result<This(Expr const &)>
  206. {};
  207. template<typename This, typename Expr>
  208. struct result<This(Expr &)>
  209. : proto::result_of::eval<Expr, Context>
  210. {};
  211. template<typename Expr>
  212. typename proto::result_of::eval<Expr, Context>::type
  213. operator ()(Expr &e) const
  214. {
  215. return proto::eval(e, this->ctx_);
  216. }
  217. template<typename Expr>
  218. typename proto::result_of::eval<Expr const, Context>::type
  219. operator ()(Expr const &e) const
  220. {
  221. return proto::eval(e, this->ctx_);
  222. }
  223. private:
  224. Context &ctx_;
  225. };
  226. /// INTERNAL ONLY
  227. ///
  228. template<typename Context>
  229. struct is_callable<eval_fun<Context> >
  230. : mpl::true_
  231. {};
  232. }}
  233. namespace boost { namespace fusion
  234. {
  235. namespace extension
  236. {
  237. template<typename Tag>
  238. struct is_sequence_impl;
  239. template<typename Tag, typename Domain>
  240. struct is_sequence_impl<proto::tag::proto_flat_view<Tag, Domain> >
  241. {
  242. template<typename Sequence>
  243. struct apply
  244. : mpl::true_
  245. {};
  246. };
  247. template<typename Tag, typename Domain>
  248. struct is_sequence_impl<proto::tag::proto_expr<Tag, Domain> >
  249. {
  250. template<typename Sequence>
  251. struct apply
  252. : mpl::true_
  253. {};
  254. };
  255. template<typename Tag>
  256. struct is_view_impl;
  257. template<typename Tag, typename Domain>
  258. struct is_view_impl<proto::tag::proto_flat_view<Tag, Domain> >
  259. {
  260. template<typename Sequence>
  261. struct apply
  262. : mpl::true_
  263. {};
  264. };
  265. template<typename Tag, typename Domain>
  266. struct is_view_impl<proto::tag::proto_expr<Tag, Domain> >
  267. {
  268. template<typename Sequence>
  269. struct apply
  270. : mpl::false_
  271. {};
  272. };
  273. template<typename Tag>
  274. struct value_of_impl;
  275. template<typename Tag, typename Domain>
  276. struct value_of_impl<proto::tag::proto_expr_iterator<Tag, Domain> >
  277. {
  278. template<
  279. typename Iterator
  280. , long Arity = proto::arity_of<typename Iterator::expr_type>::value
  281. >
  282. struct apply
  283. {
  284. typedef
  285. typename proto::result_of::child_c<
  286. typename Iterator::expr_type
  287. , Iterator::index
  288. >::value_type
  289. type;
  290. };
  291. template<typename Iterator>
  292. struct apply<Iterator, 0>
  293. {
  294. typedef
  295. typename proto::result_of::value<
  296. typename Iterator::expr_type
  297. >::value_type
  298. type;
  299. };
  300. };
  301. template<typename Tag>
  302. struct deref_impl;
  303. template<typename Tag, typename Domain>
  304. struct deref_impl<proto::tag::proto_expr_iterator<Tag, Domain> >
  305. {
  306. template<
  307. typename Iterator
  308. , long Arity = proto::arity_of<typename Iterator::expr_type>::value
  309. >
  310. struct apply
  311. {
  312. typedef
  313. typename proto::result_of::child_c<
  314. typename Iterator::expr_type &
  315. , Iterator::index
  316. >::type
  317. type;
  318. static type call(Iterator const &iter)
  319. {
  320. return proto::child_c<Iterator::index>(iter.expr);
  321. }
  322. };
  323. template<typename Iterator>
  324. struct apply<Iterator, 0>
  325. {
  326. typedef
  327. typename proto::result_of::value<
  328. typename Iterator::expr_type &
  329. >::type
  330. type;
  331. static type call(Iterator const &iter)
  332. {
  333. return proto::value(iter.expr);
  334. }
  335. };
  336. };
  337. template<typename Tag>
  338. struct advance_impl;
  339. template<typename Tag, typename Domain>
  340. struct advance_impl<proto::tag::proto_expr_iterator<Tag, Domain> >
  341. {
  342. template<typename Iterator, typename N>
  343. struct apply
  344. {
  345. typedef
  346. proto::detail::expr_iterator<
  347. typename Iterator::expr_type
  348. , Iterator::index + N::value
  349. >
  350. type;
  351. static type call(Iterator const &iter)
  352. {
  353. return type(iter.expr);
  354. }
  355. };
  356. };
  357. template<typename Tag>
  358. struct distance_impl;
  359. template<typename Tag, typename Domain>
  360. struct distance_impl<proto::tag::proto_expr_iterator<Tag, Domain> >
  361. {
  362. template<typename IteratorFrom, typename IteratorTo>
  363. struct apply
  364. : mpl::long_<IteratorTo::index - IteratorFrom::index>
  365. {};
  366. };
  367. template<typename Tag>
  368. struct next_impl;
  369. template<typename Tag, typename Domain>
  370. struct next_impl<proto::tag::proto_expr_iterator<Tag, Domain> >
  371. {
  372. template<typename Iterator>
  373. struct apply
  374. : advance_impl<proto::tag::proto_expr_iterator<Tag, Domain> >::template apply<Iterator, mpl::long_<1> >
  375. {};
  376. };
  377. template<typename Tag>
  378. struct prior_impl;
  379. template<typename Tag, typename Domain>
  380. struct prior_impl<proto::tag::proto_expr_iterator<Tag, Domain> >
  381. {
  382. template<typename Iterator>
  383. struct apply
  384. : advance_impl<proto::tag::proto_expr_iterator<Tag, Domain> >::template apply<Iterator, mpl::long_<-1> >
  385. {};
  386. };
  387. template<typename Tag>
  388. struct category_of_impl;
  389. template<typename Tag, typename Domain>
  390. struct category_of_impl<proto::tag::proto_expr<Tag, Domain> >
  391. {
  392. template<typename Sequence>
  393. struct apply
  394. {
  395. typedef random_access_traversal_tag type;
  396. };
  397. };
  398. template<typename Tag>
  399. struct size_impl;
  400. template<typename Tag, typename Domain>
  401. struct size_impl<proto::tag::proto_expr<Tag, Domain> >
  402. {
  403. template<typename Sequence>
  404. struct apply
  405. : mpl::long_<0 == Sequence::proto_arity_c ? 1 : Sequence::proto_arity_c>
  406. {};
  407. };
  408. template<typename Tag>
  409. struct begin_impl;
  410. template<typename Tag, typename Domain>
  411. struct begin_impl<proto::tag::proto_expr<Tag, Domain> >
  412. {
  413. template<typename Sequence>
  414. struct apply
  415. {
  416. typedef proto::detail::expr_iterator<Sequence, 0> type;
  417. static type call(Sequence &seq)
  418. {
  419. return type(seq);
  420. }
  421. };
  422. };
  423. template<typename Tag>
  424. struct end_impl;
  425. template<typename Tag, typename Domain>
  426. struct end_impl<proto::tag::proto_expr<Tag, Domain> >
  427. {
  428. template<typename Sequence>
  429. struct apply
  430. {
  431. typedef
  432. proto::detail::expr_iterator<
  433. Sequence
  434. , 0 == Sequence::proto_arity_c ? 1 : Sequence::proto_arity_c
  435. >
  436. type;
  437. static type call(Sequence &seq)
  438. {
  439. return type(seq);
  440. }
  441. };
  442. };
  443. template<typename Tag>
  444. struct value_at_impl;
  445. template<typename Tag, typename Domain>
  446. struct value_at_impl<proto::tag::proto_expr<Tag, Domain> >
  447. {
  448. template<
  449. typename Sequence
  450. , typename Index
  451. , long Arity = proto::arity_of<Sequence>::value
  452. >
  453. struct apply
  454. {
  455. typedef
  456. typename proto::result_of::child_c<
  457. Sequence
  458. , Index::value
  459. >::value_type
  460. type;
  461. };
  462. template<typename Sequence, typename Index>
  463. struct apply<Sequence, Index, 0>
  464. {
  465. typedef
  466. typename proto::result_of::value<
  467. Sequence
  468. >::value_type
  469. type;
  470. };
  471. };
  472. template<typename Tag>
  473. struct at_impl;
  474. template<typename Tag, typename Domain>
  475. struct at_impl<proto::tag::proto_expr<Tag, Domain> >
  476. {
  477. template<
  478. typename Sequence
  479. , typename Index
  480. , long Arity = proto::arity_of<Sequence>::value
  481. >
  482. struct apply
  483. {
  484. typedef
  485. typename proto::result_of::child_c<
  486. Sequence &
  487. , Index::value
  488. >::type
  489. type;
  490. static type call(Sequence &seq)
  491. {
  492. return proto::child_c<Index::value>(seq);
  493. }
  494. };
  495. template<typename Sequence, typename Index>
  496. struct apply<Sequence, Index, 0>
  497. {
  498. typedef
  499. typename proto::result_of::value<
  500. Sequence &
  501. >::type
  502. type;
  503. static type call(Sequence &seq)
  504. {
  505. return proto::value(seq);
  506. }
  507. };
  508. };
  509. template<typename Tag>
  510. struct convert_impl;
  511. template<typename Tag, typename Domain>
  512. struct convert_impl<proto::tag::proto_expr<Tag, Domain> >
  513. {
  514. template<typename Sequence>
  515. struct apply
  516. {
  517. typedef
  518. typename proto::result_of::unpack_expr<
  519. Tag
  520. , Domain
  521. , Sequence
  522. >::type
  523. type;
  524. static type call(Sequence& seq)
  525. {
  526. return proto::unpack_expr<Tag, Domain>(seq);
  527. }
  528. };
  529. };
  530. template<typename Tag, typename Domain>
  531. struct convert_impl<proto::tag::proto_flat_view<Tag, Domain> >
  532. {
  533. template<typename Sequence>
  534. struct apply
  535. {
  536. typedef
  537. typename proto::result_of::unpack_expr<
  538. Tag
  539. , Domain
  540. , Sequence
  541. >::type
  542. type;
  543. static type call(Sequence& seq)
  544. {
  545. return proto::unpack_expr<Tag, Domain>(seq);
  546. }
  547. };
  548. };
  549. template<typename Tag>
  550. struct is_segmented_impl;
  551. template<typename Tag, typename Domain>
  552. struct is_segmented_impl<proto::tag::proto_flat_view<Tag, Domain> >
  553. {
  554. template<typename Iterator>
  555. struct apply
  556. : mpl::true_
  557. {};
  558. };
  559. template<typename Tag>
  560. struct segments_impl;
  561. template<typename Tag, typename Domain>
  562. struct segments_impl<proto::tag::proto_flat_view<Tag, Domain> >
  563. {
  564. template<typename Sequence>
  565. struct apply
  566. {
  567. typedef typename Sequence::segments_type const &type;
  568. static type call(Sequence &sequence)
  569. {
  570. return sequence.segs_;
  571. }
  572. };
  573. };
  574. template<typename Tag, typename Domain>
  575. struct category_of_impl<proto::tag::proto_flat_view<Tag, Domain> >
  576. {
  577. template<typename Sequence>
  578. struct apply
  579. {
  580. typedef forward_traversal_tag type;
  581. };
  582. };
  583. }
  584. namespace traits
  585. {
  586. template<typename Seq1, typename Seq2>
  587. struct enable_equality<
  588. Seq1
  589. , Seq2
  590. , typename enable_if_c<
  591. mpl::or_<
  592. proto::is_expr<Seq1>
  593. , proto::is_expr<Seq2>
  594. >::value
  595. >::type
  596. >
  597. : mpl::false_
  598. {};
  599. template<typename Seq1, typename Seq2>
  600. struct enable_comparison<
  601. Seq1
  602. , Seq2
  603. , typename enable_if_c<
  604. mpl::or_<
  605. proto::is_expr<Seq1>
  606. , proto::is_expr<Seq2>
  607. >::value
  608. >::type
  609. >
  610. : mpl::false_
  611. {};
  612. }
  613. }}
  614. namespace boost { namespace mpl
  615. {
  616. template<typename Tag, typename Args, long Arity>
  617. struct sequence_tag< proto::expr<Tag, Args, Arity> >
  618. {
  619. typedef fusion::fusion_sequence_tag type;
  620. };
  621. template<typename Tag, typename Args, long Arity>
  622. struct sequence_tag< proto::basic_expr<Tag, Args, Arity> >
  623. {
  624. typedef fusion::fusion_sequence_tag type;
  625. };
  626. }}
  627. #ifdef BOOST_MSVC
  628. #pragma warning(pop)
  629. #endif
  630. #endif