/////////////////////////////////////////////////////////////////////////////// /// \file fusion.hpp /// Make any Proto expression a valid Fusion sequence // // Copyright 2008 Eric Niebler. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROTO_FUSION_HPP_EAN_11_04_2006 #define BOOST_PROTO_FUSION_HPP_EAN_11_04_2006 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef BOOST_MSVC #pragma warning(push) #pragma warning(disable : 4510) // default constructor could not be generated #pragma warning(disable : 4512) // assignment operator could not be generated #pragma warning(disable : 4610) // can never be instantiated - user defined constructor required #endif namespace boost { namespace proto { namespace detail { template struct expr_iterator : fusion::iterator_base > { typedef Expr expr_type; static const long index = Pos; typedef fusion::random_access_traversal_tag category; typedef tag::proto_expr_iterator< typename Expr::proto_tag , typename Expr::proto_domain > fusion_tag; explicit expr_iterator(Expr &e) : expr(e) {} Expr &expr; }; template struct as_element { template struct result; template struct result : result {}; template struct result : mpl::if_c< is_same::value , flat_view , fusion::single_view > {}; template typename result::type const operator ()(Expr &e) const { return typename result::type(e); } template typename result::type const operator ()(Expr const &e) const { return typename result::type(e); } }; template struct flat_view : fusion::sequence_base > { typedef fusion::forward_traversal_tag category; typedef tag::proto_flat_view< typename Expr::proto_tag , typename Expr::proto_domain > fusion_tag; typedef typename fusion::result_of::as_list< typename fusion::result_of::transform< Expr , as_element >::type >::type segments_type; explicit flat_view(Expr &e) : segs_(fusion::as_list(fusion::transform(e, as_element()))) {} segments_type segs_; }; } namespace result_of { template struct flatten : flatten {}; template struct flatten { typedef detail::flat_view type; }; } namespace functional { /// \brief A PolymorphicFunctionObject type that returns a "flattened" /// view of a Proto expression tree. /// /// A PolymorphicFunctionObject type that returns a "flattened" /// view of a Proto expression tree. For a tree with a top-most node /// tag of type \c T, the elements of the flattened sequence are /// determined by recursing into each child node with the same /// tag type and returning those nodes of different type. So for /// instance, the Proto expression tree corresponding to the /// expression a | b | c has a flattened view with elements /// [a, b, c], even though the tree is grouped as /// ((a | b) | c). struct flatten { BOOST_PROTO_CALLABLE() template struct result; template struct result : result {}; template struct result { typedef proto::detail::flat_view type; }; template proto::detail::flat_view const operator ()(Expr &e) const { return proto::detail::flat_view(e); } template proto::detail::flat_view const operator ()(Expr const &e) const { return proto::detail::flat_view(e); } }; } /// \brief A function that returns a "flattened" /// view of a Proto expression tree. /// /// For a tree with a top-most node /// tag of type \c T, the elements of the flattened sequence are /// determined by recursing into each child node with the same /// tag type and returning those nodes of different type. So for /// instance, the Proto expression tree corresponding to the /// expression a | b | c has a flattened view with elements /// [a, b, c], even though the tree is grouped as /// ((a | b) | c). template proto::detail::flat_view const flatten(Expr &e) { return proto::detail::flat_view(e); } /// \overload /// template proto::detail::flat_view const flatten(Expr const &e) { return proto::detail::flat_view(e); } /// INTERNAL ONLY /// template struct eval_fun : proto::callable { explicit eval_fun(Context &ctx) : ctx_(ctx) {} template struct result; template struct result : result {}; template struct result : proto::result_of::eval {}; template typename proto::result_of::eval::type operator ()(Expr &e) const { return proto::eval(e, this->ctx_); } template typename proto::result_of::eval::type operator ()(Expr const &e) const { return proto::eval(e, this->ctx_); } private: Context &ctx_; }; /// INTERNAL ONLY /// template struct is_callable > : mpl::true_ {}; }} namespace boost { namespace fusion { namespace extension { template struct is_sequence_impl; template struct is_sequence_impl > { template struct apply : mpl::true_ {}; }; template struct is_sequence_impl > { template struct apply : mpl::true_ {}; }; template struct is_view_impl; template struct is_view_impl > { template struct apply : mpl::true_ {}; }; template struct is_view_impl > { template struct apply : mpl::false_ {}; }; template struct value_of_impl; template struct value_of_impl > { template< typename Iterator , long Arity = proto::arity_of::value > struct apply { typedef typename proto::result_of::child_c< typename Iterator::expr_type , Iterator::index >::value_type type; }; template struct apply { typedef typename proto::result_of::value< typename Iterator::expr_type >::value_type type; }; }; template struct deref_impl; template struct deref_impl > { template< typename Iterator , long Arity = proto::arity_of::value > struct apply { typedef typename proto::result_of::child_c< typename Iterator::expr_type & , Iterator::index >::type type; static type call(Iterator const &iter) { return proto::child_c(iter.expr); } }; template struct apply { typedef typename proto::result_of::value< typename Iterator::expr_type & >::type type; static type call(Iterator const &iter) { return proto::value(iter.expr); } }; }; template struct advance_impl; template struct advance_impl > { template struct apply { typedef proto::detail::expr_iterator< typename Iterator::expr_type , Iterator::index + N::value > type; static type call(Iterator const &iter) { return type(iter.expr); } }; }; template struct distance_impl; template struct distance_impl > { template struct apply : mpl::long_ {}; }; template struct next_impl; template struct next_impl > { template struct apply : advance_impl >::template apply > {}; }; template struct prior_impl; template struct prior_impl > { template struct apply : advance_impl >::template apply > {}; }; template struct category_of_impl; template struct category_of_impl > { template struct apply { typedef random_access_traversal_tag type; }; }; template struct size_impl; template struct size_impl > { template struct apply : mpl::long_<0 == Sequence::proto_arity_c ? 1 : Sequence::proto_arity_c> {}; }; template struct begin_impl; template struct begin_impl > { template struct apply { typedef proto::detail::expr_iterator type; static type call(Sequence &seq) { return type(seq); } }; }; template struct end_impl; template struct end_impl > { template struct apply { typedef proto::detail::expr_iterator< Sequence , 0 == Sequence::proto_arity_c ? 1 : Sequence::proto_arity_c > type; static type call(Sequence &seq) { return type(seq); } }; }; template struct value_at_impl; template struct value_at_impl > { template< typename Sequence , typename Index , long Arity = proto::arity_of::value > struct apply { typedef typename proto::result_of::child_c< Sequence , Index::value >::value_type type; }; template struct apply { typedef typename proto::result_of::value< Sequence >::value_type type; }; }; template struct at_impl; template struct at_impl > { template< typename Sequence , typename Index , long Arity = proto::arity_of::value > struct apply { typedef typename proto::result_of::child_c< Sequence & , Index::value >::type type; static type call(Sequence &seq) { return proto::child_c(seq); } }; template struct apply { typedef typename proto::result_of::value< Sequence & >::type type; static type call(Sequence &seq) { return proto::value(seq); } }; }; template struct convert_impl; template struct convert_impl > { template struct apply { typedef typename proto::result_of::unpack_expr< Tag , Domain , Sequence >::type type; static type call(Sequence& seq) { return proto::unpack_expr(seq); } }; }; template struct convert_impl > { template struct apply { typedef typename proto::result_of::unpack_expr< Tag , Domain , Sequence >::type type; static type call(Sequence& seq) { return proto::unpack_expr(seq); } }; }; template struct is_segmented_impl; template struct is_segmented_impl > { template struct apply : mpl::true_ {}; }; template struct segments_impl; template struct segments_impl > { template struct apply { typedef typename Sequence::segments_type const &type; static type call(Sequence &sequence) { return sequence.segs_; } }; }; template struct category_of_impl > { template struct apply { typedef forward_traversal_tag type; }; }; } namespace traits { template struct enable_equality< Seq1 , Seq2 , typename enable_if_c< mpl::or_< proto::is_expr , proto::is_expr >::value >::type > : mpl::false_ {}; template struct enable_comparison< Seq1 , Seq2 , typename enable_if_c< mpl::or_< proto::is_expr , proto::is_expr >::value >::type > : mpl::false_ {}; } }} namespace boost { namespace mpl { template struct sequence_tag< proto::expr > { typedef fusion::fusion_sequence_tag type; }; template struct sequence_tag< proto::basic_expr > { typedef fusion::fusion_sequence_tag type; }; }} #ifdef BOOST_MSVC #pragma warning(pop) #endif #endif