Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:33

0001 ///////////////////////////////////////////////////////////////////////////////
0002 /// \file fusion.hpp
0003 /// Make any Proto expression a valid Fusion sequence
0004 //
0005 //  Copyright 2008 Eric Niebler. Distributed under the Boost
0006 //  Software License, Version 1.0. (See accompanying file
0007 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0008 
0009 #ifndef BOOST_PROTO_FUSION_HPP_EAN_11_04_2006
0010 #define BOOST_PROTO_FUSION_HPP_EAN_11_04_2006
0011 
0012 #include <boost/config.hpp>
0013 #include <boost/mpl/if.hpp>
0014 #include <boost/mpl/bool.hpp>
0015 #include <boost/mpl/long.hpp>
0016 #include <boost/mpl/sequence_tag_fwd.hpp>
0017 #include <boost/utility/enable_if.hpp>
0018 #include <boost/fusion/include/is_view.hpp>
0019 #include <boost/fusion/include/tag_of_fwd.hpp>
0020 #include <boost/fusion/include/category_of.hpp>
0021 #include <boost/fusion/include/iterator_base.hpp>
0022 #include <boost/fusion/include/intrinsic.hpp>
0023 #include <boost/fusion/include/single_view.hpp>
0024 #include <boost/fusion/include/transform.hpp>
0025 #include <boost/fusion/include/as_list.hpp>
0026 #include <boost/fusion/include/is_segmented.hpp>
0027 #include <boost/fusion/sequence/comparison/enable_comparison.hpp>
0028 #include <boost/proto/proto_fwd.hpp>
0029 #include <boost/proto/traits.hpp>
0030 #include <boost/proto/eval.hpp>
0031 #include <boost/proto/make_expr.hpp>
0032 
0033 #ifdef BOOST_MSVC
0034 #pragma warning(push)
0035 #pragma warning(disable : 4510) // default constructor could not be generated
0036 #pragma warning(disable : 4512) // assignment operator could not be generated
0037 #pragma warning(disable : 4610) // can never be instantiated - user defined constructor required
0038 #endif
0039 
0040 namespace boost { namespace proto
0041 {
0042     namespace detail
0043     {
0044         template<typename Expr, long Pos>
0045         struct expr_iterator
0046           : fusion::iterator_base<expr_iterator<Expr, Pos> >
0047         {
0048             typedef Expr expr_type;
0049             static const long index = Pos;
0050             typedef fusion::random_access_traversal_tag category;
0051             typedef
0052                 tag::proto_expr_iterator<
0053                     typename Expr::proto_tag
0054                   , typename Expr::proto_domain
0055                 >
0056             fusion_tag;
0057 
0058             explicit expr_iterator(Expr &e)
0059               : expr(e)
0060             {}
0061 
0062             Expr &expr;
0063         };
0064 
0065         template<typename Tag>
0066         struct as_element
0067         {
0068             template<typename Sig>
0069             struct result;
0070 
0071             template<typename This, typename Expr>
0072             struct result<This(Expr)>
0073               : result<This(Expr const &)>
0074             {};
0075 
0076             template<typename This, typename Expr>
0077             struct result<This(Expr &)>
0078               : mpl::if_c<
0079                     is_same<Tag, typename Expr::proto_tag>::value
0080                   , flat_view<Expr>
0081                   , fusion::single_view<Expr &>
0082                 >
0083             {};
0084 
0085             template<typename Expr>
0086             typename result<as_element(Expr &)>::type const
0087             operator ()(Expr &e) const
0088             {
0089                 return typename result<as_element(Expr &)>::type(e);
0090             }
0091 
0092             template<typename Expr>
0093             typename result<as_element(Expr const &)>::type const
0094             operator ()(Expr const &e) const
0095             {
0096                 return typename result<as_element(Expr const &)>::type(e);
0097             }
0098         };
0099 
0100         template<typename Expr>
0101         struct flat_view
0102           : fusion::sequence_base<flat_view<Expr> >
0103         {
0104             typedef fusion::forward_traversal_tag category;
0105             typedef
0106                 tag::proto_flat_view<
0107                     typename Expr::proto_tag
0108                   , typename Expr::proto_domain
0109                 >
0110             fusion_tag;
0111             typedef
0112                 typename fusion::result_of::as_list<
0113                     typename fusion::result_of::transform<
0114                         Expr
0115                       , as_element<typename Expr::proto_tag>
0116                     >::type
0117                 >::type
0118             segments_type;
0119 
0120             explicit flat_view(Expr &e)
0121               : segs_(fusion::as_list(fusion::transform(e, as_element<typename Expr::proto_tag>())))
0122             {}
0123 
0124             segments_type segs_;
0125         };
0126     }
0127 
0128     namespace result_of
0129     {
0130         template<typename Expr>
0131         struct flatten
0132           : flatten<Expr const &>
0133         {};
0134 
0135         template<typename Expr>
0136         struct flatten<Expr &>
0137         {
0138             typedef detail::flat_view<Expr> type;
0139         };
0140     }
0141 
0142     namespace functional
0143     {
0144         /// \brief A PolymorphicFunctionObject type that returns a "flattened"
0145         /// view of a Proto expression tree.
0146         ///
0147         /// A PolymorphicFunctionObject type that returns a "flattened"
0148         /// view of a Proto expression tree. For a tree with a top-most node
0149         /// tag of type \c T, the elements of the flattened sequence are
0150         /// determined by recursing into each child node with the same
0151         /// tag type and returning those nodes of different type. So for
0152         /// instance, the Proto expression tree corresponding to the
0153         /// expression <tt>a | b | c</tt> has a flattened view with elements
0154         /// [a, b, c], even though the tree is grouped as
0155         /// <tt>((a | b) | c)</tt>.
0156         struct flatten
0157         {
0158             BOOST_PROTO_CALLABLE()
0159 
0160             template<typename Sig>
0161             struct result;
0162 
0163             template<typename This, typename Expr>
0164             struct result<This(Expr)>
0165               : result<This(Expr const &)>
0166             {};
0167 
0168             template<typename This, typename Expr>
0169             struct result<This(Expr &)>
0170             {
0171                 typedef proto::detail::flat_view<Expr> type;
0172             };
0173 
0174             template<typename Expr>
0175             proto::detail::flat_view<Expr> const
0176             operator ()(Expr &e) const
0177             {
0178                 return proto::detail::flat_view<Expr>(e);
0179             }
0180 
0181             template<typename Expr>
0182             proto::detail::flat_view<Expr const> const
0183             operator ()(Expr const &e) const
0184             {
0185                 return proto::detail::flat_view<Expr const>(e);
0186             }
0187         };
0188     }
0189 
0190     /// \brief A function that returns a "flattened"
0191     /// view of a Proto expression tree.
0192     ///
0193     /// For a tree with a top-most node
0194     /// tag of type \c T, the elements of the flattened sequence are
0195     /// determined by recursing into each child node with the same
0196     /// tag type and returning those nodes of different type. So for
0197     /// instance, the Proto expression tree corresponding to the
0198     /// expression <tt>a | b | c</tt> has a flattened view with elements
0199     /// [a, b, c], even though the tree is grouped as
0200     /// <tt>((a | b) | c)</tt>.
0201     template<typename Expr>
0202     proto::detail::flat_view<Expr> const
0203     flatten(Expr &e)
0204     {
0205         return proto::detail::flat_view<Expr>(e);
0206     }
0207 
0208     /// \overload
0209     ///
0210     template<typename Expr>
0211     proto::detail::flat_view<Expr const> const
0212     flatten(Expr const &e)
0213     {
0214         return proto::detail::flat_view<Expr const>(e);
0215     }
0216 
0217     /// INTERNAL ONLY
0218     ///
0219     template<typename Context>
0220     struct eval_fun
0221       : proto::callable
0222     {
0223         explicit eval_fun(Context &ctx)
0224           : ctx_(ctx)
0225         {}
0226 
0227         template<typename Sig>
0228         struct result;
0229 
0230         template<typename This, typename Expr>
0231         struct result<This(Expr)>
0232           : result<This(Expr const &)>
0233         {};
0234 
0235         template<typename This, typename Expr>
0236         struct result<This(Expr &)>
0237           : proto::result_of::eval<Expr, Context>
0238         {};
0239 
0240         template<typename Expr>
0241         typename proto::result_of::eval<Expr, Context>::type
0242         operator ()(Expr &e) const
0243         {
0244             return proto::eval(e, this->ctx_);
0245         }
0246 
0247         template<typename Expr>
0248         typename proto::result_of::eval<Expr const, Context>::type
0249         operator ()(Expr const &e) const
0250         {
0251             return proto::eval(e, this->ctx_);
0252         }
0253 
0254     private:
0255         Context &ctx_;
0256     };
0257 
0258     /// INTERNAL ONLY
0259     ///
0260     template<typename Context>
0261     struct is_callable<eval_fun<Context> >
0262       : mpl::true_
0263     {};
0264 }}
0265 
0266 namespace boost { namespace fusion
0267 {
0268     namespace extension
0269     {
0270         template<typename Tag>
0271         struct is_sequence_impl;
0272 
0273         template<typename Tag, typename Domain>
0274         struct is_sequence_impl<proto::tag::proto_flat_view<Tag, Domain> >
0275         {
0276             template<typename Sequence>
0277             struct apply
0278               : mpl::true_
0279             {};
0280         };
0281 
0282         template<typename Tag, typename Domain>
0283         struct is_sequence_impl<proto::tag::proto_expr<Tag, Domain> >
0284         {
0285             template<typename Sequence>
0286             struct apply
0287               : mpl::true_
0288             {};
0289         };
0290 
0291         template<typename Tag>
0292         struct is_view_impl;
0293 
0294         template<typename Tag, typename Domain>
0295         struct is_view_impl<proto::tag::proto_flat_view<Tag, Domain> >
0296         {
0297             template<typename Sequence>
0298             struct apply
0299               : mpl::true_
0300             {};
0301         };
0302 
0303         template<typename Tag, typename Domain>
0304         struct is_view_impl<proto::tag::proto_expr<Tag, Domain> >
0305         {
0306             template<typename Sequence>
0307             struct apply
0308               : mpl::false_
0309             {};
0310         };
0311 
0312         template<typename Tag>
0313         struct value_of_impl;
0314 
0315         template<typename Tag, typename Domain>
0316         struct value_of_impl<proto::tag::proto_expr_iterator<Tag, Domain> >
0317         {
0318             template<
0319                 typename Iterator
0320               , long Arity = proto::arity_of<typename Iterator::expr_type>::value
0321             >
0322             struct apply
0323             {
0324                 typedef
0325                     typename proto::result_of::child_c<
0326                         typename Iterator::expr_type
0327                       , Iterator::index
0328                     >::value_type
0329                 type;
0330             };
0331 
0332             template<typename Iterator>
0333             struct apply<Iterator, 0>
0334             {
0335                 typedef
0336                     typename proto::result_of::value<
0337                         typename Iterator::expr_type
0338                     >::value_type
0339                 type;
0340             };
0341         };
0342 
0343         template<typename Tag>
0344         struct deref_impl;
0345 
0346         template<typename Tag, typename Domain>
0347         struct deref_impl<proto::tag::proto_expr_iterator<Tag, Domain> >
0348         {
0349             template<
0350                 typename Iterator
0351               , long Arity = proto::arity_of<typename Iterator::expr_type>::value
0352             >
0353             struct apply
0354             {
0355                 typedef
0356                     typename proto::result_of::child_c<
0357                         typename Iterator::expr_type &
0358                       , Iterator::index
0359                     >::type
0360                 type;
0361 
0362                 static type call(Iterator const &iter)
0363                 {
0364                     return proto::child_c<Iterator::index>(iter.expr);
0365                 }
0366             };
0367 
0368             template<typename Iterator>
0369             struct apply<Iterator, 0>
0370             {
0371                 typedef
0372                     typename proto::result_of::value<
0373                         typename Iterator::expr_type &
0374                     >::type
0375                 type;
0376 
0377                 static type call(Iterator const &iter)
0378                 {
0379                     return proto::value(iter.expr);
0380                 }
0381             };
0382         };
0383 
0384         template<typename Tag>
0385         struct advance_impl;
0386 
0387         template<typename Tag, typename Domain>
0388         struct advance_impl<proto::tag::proto_expr_iterator<Tag, Domain> >
0389         {
0390             template<typename Iterator, typename N>
0391             struct apply
0392             {
0393                 typedef
0394                     proto::detail::expr_iterator<
0395                         typename Iterator::expr_type
0396                       , Iterator::index + N::value
0397                     >
0398                 type;
0399 
0400                 static type call(Iterator const &iter)
0401                 {
0402                     return type(iter.expr);
0403                 }
0404             };
0405         };
0406 
0407         template<typename Tag>
0408         struct distance_impl;
0409 
0410         template<typename Tag, typename Domain>
0411         struct distance_impl<proto::tag::proto_expr_iterator<Tag, Domain> >
0412         {
0413             template<typename IteratorFrom, typename IteratorTo>
0414             struct apply
0415               : mpl::long_<IteratorTo::index - IteratorFrom::index>
0416             {};
0417         };
0418 
0419         template<typename Tag>
0420         struct next_impl;
0421 
0422         template<typename Tag, typename Domain>
0423         struct next_impl<proto::tag::proto_expr_iterator<Tag, Domain> >
0424         {
0425             template<typename Iterator>
0426             struct apply
0427               : advance_impl<proto::tag::proto_expr_iterator<Tag, Domain> >::template apply<Iterator, mpl::long_<1> >
0428             {};
0429         };
0430 
0431         template<typename Tag>
0432         struct prior_impl;
0433 
0434         template<typename Tag, typename Domain>
0435         struct prior_impl<proto::tag::proto_expr_iterator<Tag, Domain> >
0436         {
0437             template<typename Iterator>
0438             struct apply
0439               : advance_impl<proto::tag::proto_expr_iterator<Tag, Domain> >::template apply<Iterator, mpl::long_<-1> >
0440             {};
0441         };
0442 
0443         template<typename Tag>
0444         struct category_of_impl;
0445 
0446         template<typename Tag, typename Domain>
0447         struct category_of_impl<proto::tag::proto_expr<Tag, Domain> >
0448         {
0449             template<typename Sequence>
0450             struct apply
0451             {
0452                 typedef random_access_traversal_tag type;
0453             };
0454         };
0455 
0456         template<typename Tag>
0457         struct size_impl;
0458 
0459         template<typename Tag, typename Domain>
0460         struct size_impl<proto::tag::proto_expr<Tag, Domain> >
0461         {
0462             template<typename Sequence>
0463             struct apply
0464               : mpl::long_<0 == Sequence::proto_arity_c ? 1 : Sequence::proto_arity_c>
0465             {};
0466         };
0467 
0468         template<typename Tag>
0469         struct begin_impl;
0470 
0471         template<typename Tag, typename Domain>
0472         struct begin_impl<proto::tag::proto_expr<Tag, Domain> >
0473         {
0474             template<typename Sequence>
0475             struct apply
0476             {
0477                 typedef proto::detail::expr_iterator<Sequence, 0> type;
0478 
0479                 static type call(Sequence &seq)
0480                 {
0481                     return type(seq);
0482                 }
0483             };
0484         };
0485 
0486         template<typename Tag>
0487         struct end_impl;
0488 
0489         template<typename Tag, typename Domain>
0490         struct end_impl<proto::tag::proto_expr<Tag, Domain> >
0491         {
0492             template<typename Sequence>
0493             struct apply
0494             {
0495                 typedef
0496                     proto::detail::expr_iterator<
0497                         Sequence
0498                       , 0 == Sequence::proto_arity_c ? 1 : Sequence::proto_arity_c
0499                     >
0500                 type;
0501 
0502                 static type call(Sequence &seq)
0503                 {
0504                     return type(seq);
0505                 }
0506             };
0507         };
0508 
0509         template<typename Tag>
0510         struct value_at_impl;
0511 
0512         template<typename Tag, typename Domain>
0513         struct value_at_impl<proto::tag::proto_expr<Tag, Domain> >
0514         {
0515             template<
0516                 typename Sequence
0517               , typename Index
0518               , long Arity = proto::arity_of<Sequence>::value
0519             >
0520             struct apply
0521             {
0522                 typedef
0523                     typename proto::result_of::child_c<
0524                         Sequence
0525                       , Index::value
0526                     >::value_type
0527                 type;
0528             };
0529 
0530             template<typename Sequence, typename Index>
0531             struct apply<Sequence, Index, 0>
0532             {
0533                 typedef
0534                     typename proto::result_of::value<
0535                         Sequence
0536                     >::value_type
0537                 type;
0538             };
0539         };
0540 
0541         template<typename Tag>
0542         struct at_impl;
0543 
0544         template<typename Tag, typename Domain>
0545         struct at_impl<proto::tag::proto_expr<Tag, Domain> >
0546         {
0547             template<
0548                 typename Sequence
0549               , typename Index
0550               , long Arity = proto::arity_of<Sequence>::value
0551             >
0552             struct apply
0553             {
0554                 typedef
0555                     typename proto::result_of::child_c<
0556                         Sequence &
0557                       , Index::value
0558                     >::type
0559                 type;
0560 
0561                 static type call(Sequence &seq)
0562                 {
0563                     return proto::child_c<Index::value>(seq);
0564                 }
0565             };
0566 
0567             template<typename Sequence, typename Index>
0568             struct apply<Sequence, Index, 0>
0569             {
0570                 typedef
0571                     typename proto::result_of::value<
0572                         Sequence &
0573                     >::type
0574                 type;
0575 
0576                 static type call(Sequence &seq)
0577                 {
0578                     return proto::value(seq);
0579                 }
0580             };
0581         };
0582 
0583         template<typename Tag>
0584         struct convert_impl;
0585 
0586         template<typename Tag, typename Domain>
0587         struct convert_impl<proto::tag::proto_expr<Tag, Domain> >
0588         {
0589             template<typename Sequence>
0590             struct apply
0591             {
0592                 typedef
0593                     typename proto::result_of::unpack_expr<
0594                         Tag
0595                       , Domain
0596                       , Sequence
0597                     >::type
0598                 type;
0599 
0600                 static type call(Sequence& seq)
0601                 {
0602                     return proto::unpack_expr<Tag, Domain>(seq);
0603                 }
0604             };
0605         };
0606 
0607         template<typename Tag, typename Domain>
0608         struct convert_impl<proto::tag::proto_flat_view<Tag, Domain> >
0609         {
0610             template<typename Sequence>
0611             struct apply
0612             {
0613                 typedef
0614                     typename proto::result_of::unpack_expr<
0615                         Tag
0616                       , Domain
0617                       , Sequence
0618                     >::type
0619                 type;
0620 
0621                 static type call(Sequence& seq)
0622                 {
0623                     return proto::unpack_expr<Tag, Domain>(seq);
0624                 }
0625             };
0626         };
0627 
0628         template<typename Tag>
0629         struct is_segmented_impl;
0630 
0631         template<typename Tag, typename Domain>
0632         struct is_segmented_impl<proto::tag::proto_flat_view<Tag, Domain> >
0633         {
0634             template<typename Iterator>
0635             struct apply
0636               : mpl::true_
0637             {};
0638         };
0639 
0640         template<typename Tag>
0641         struct segments_impl;
0642 
0643         template<typename Tag, typename Domain>
0644         struct segments_impl<proto::tag::proto_flat_view<Tag, Domain> >
0645         {
0646             template<typename Sequence>
0647             struct apply
0648             {
0649                 typedef typename Sequence::segments_type const &type;
0650                             
0651                 static type call(Sequence &sequence)
0652                 {
0653                     return sequence.segs_;
0654                 }
0655             };
0656         };
0657 
0658         template<typename Tag, typename Domain>
0659         struct category_of_impl<proto::tag::proto_flat_view<Tag, Domain> >
0660         {
0661             template<typename Sequence>
0662             struct apply
0663             {
0664                 typedef forward_traversal_tag type;
0665             };
0666         };
0667     }
0668 
0669     namespace traits
0670     {
0671         template<typename Seq1, typename Seq2>
0672         struct enable_equality<
0673             Seq1
0674           , Seq2
0675           , typename enable_if_c<
0676                 mpl::or_<
0677                     proto::is_expr<Seq1>
0678                   , proto::is_expr<Seq2>
0679                 >::value
0680             >::type
0681         >
0682             : mpl::false_
0683         {};
0684 
0685         template<typename Seq1, typename Seq2>
0686         struct enable_comparison<
0687             Seq1
0688           , Seq2
0689           , typename enable_if_c<
0690                 mpl::or_<
0691                     proto::is_expr<Seq1>
0692                   , proto::is_expr<Seq2>
0693                 >::value
0694             >::type
0695         >
0696           : mpl::false_
0697         {};
0698     }
0699 }}
0700 
0701 namespace boost { namespace mpl
0702 {
0703     template<typename Tag, typename Args, long Arity>
0704     struct sequence_tag< proto::expr<Tag, Args, Arity> >
0705     {
0706         typedef fusion::fusion_sequence_tag type;
0707     };
0708 
0709     template<typename Tag, typename Args, long Arity>
0710     struct sequence_tag< proto::basic_expr<Tag, Args, Arity> >
0711     {
0712         typedef fusion::fusion_sequence_tag type;
0713     };
0714 }}
0715 
0716 #ifdef BOOST_MSVC
0717 #pragma warning(pop)
0718 #endif
0719 
0720 #endif