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