fusion.hpp 21 KB

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