[ create a new paste ] login | about

Link: http://codepad.org/A7HnOvgd    [ raw code | fork | 1 comment ]

eric_niebler - C++, pasted on Mar 3:
#include <iostream>
#include <boost/proto/proto.hpp>
#include <boost/proto/proto_typeof.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/push_back.hpp>

namespace mpl = boost::mpl;
namespace proto = boost::proto;
namespace fusion = boost::fusion;
using proto::_;

template<typename Int>
struct split_
{
    friend std::ostream &operator<<(std::ostream &sout, split_<Int> const &)
    {
        return sout << "split<" << Int::value << ">";
    }
};

proto::terminal<split_<mpl::int_<0> > >::type split = {{}};

struct first : proto::callable
{
    template<typename Sig>
    struct result;

    template<typename This, typename Pair>
    struct result<This(Pair)>
    {
        typedef typename boost::remove_reference<Pair>::type::first_type type;
    };
    
    template<typename Pair>
    typename Pair::first_type operator()(Pair const &p) const
    {
        return p.first;
    }
};

struct second : proto::callable
{
    template<typename Sig>
    struct result;

    template<typename This, typename Pair>
    struct result<This(Pair)>
    {
        typedef typename boost::remove_reference<Pair>::type::second_type type;
    };
    
    template<typename Pair>
    typename Pair::second_type operator()(Pair const &p) const
    {
        return p.second;
    }
};

struct make_pair : proto::callable
{
    template<typename Sig>
    struct result;

    template<typename This, typename First, typename Second>
    struct result<This(First, Second)>
    {
        typedef
            std::pair<
                typename boost::remove_const<typename boost::remove_reference<First>::type>::type
              , typename boost::remove_const<typename boost::remove_reference<Second>::type>::type
            >
        type;
    };

    template<typename First, typename Second>
    std::pair<First, Second> operator()(First const &first, Second const &second) const
    {
        return std::make_pair(first, second);
    }
};

struct push_back : proto::callable
{
    template<typename Sig>
    struct result;

    template<typename This, typename Cont, typename Elem>
    struct result<This(Cont, Elem)>
      : fusion::result_of::push_back<
            typename boost::add_const<typename boost::remove_reference<Cont>::type>::type
          , typename boost::remove_const<typename boost::remove_reference<Elem>::type>::type
        >
    {};

    template<typename Cont, typename Elem>
    typename fusion::result_of::push_back<Cont const, Elem>::type
    operator()(Cont const &cont, Elem const &elem) const
    {
        return fusion::push_back(cont, elem);
    }
};

#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
#define _make_function(x,y) call<proto::_make_function(x,y)>
#define make_pair(x,y) proto::call<make_pair(x,y)>
#define push_back(x,y) proto::call<push_back(x,y)>
#define first(x) proto::call<first(x)>
#define second(x) proto::call<second(x)>
#define Renumber(x,y) proto::call<Renumber(x,y)>
#endif

struct Renumber;

struct Iterate
  : proto::fold<
        _
      , make_pair(
            fusion::vector0()
          , proto::_state
        )
      , make_pair(
            push_back(first(proto::_state), first(Renumber(_, second(proto::_state))))
          , proto::make<second(Renumber(_, second(proto::_state)))>
        )
    >
{};

// A transform that replaces all split_<0> terminals
// with consecutively numbered split_<N> terminals
struct Renumber
  : proto::or_<
        proto::when<
            proto::terminal<_>
          , make_pair(_, proto::_state)
        >
      , proto::when<
            proto::function<proto::terminal<split_<_> >, _>
          , make_pair(
                proto::_make_function(
                    proto::make<split_<proto::_state> >
                  , first(Renumber(proto::_child1, mpl::next<proto::_state>()))
                )
              , second(Renumber(proto::_child1, mpl::next<proto::_state>()))
            )
        >
      , proto::otherwise<
            make_pair(
                proto::lazy<
                    proto::functional::unpack_expr< proto::tag_of<_>() >(first(Iterate))
                >
              , proto::make<second(Iterate)>
            )
        >
    >
{};

#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
#undef _make_function
#undef make_pair
#undef push_back
#undef first
#undef second
#undef Renumber
#endif

int main()
{
    proto::literal<int> i(0);
    BOOST_PROTO_AUTO(e, i + split(split(i)) + split( i * split( i - i ) ));

    proto::display_expr(e);
    std::cout << std::endl;

    proto::display_expr(Renumber()(e, mpl::int_<0>()).first);
    std::cout << std::endl;
}


Create a new paste based on this one


Comments:
posted by eric_niebler on Mar 3
For me, this program displays ...

plus(
plus(
terminal(0)
, function(
terminal(split<0>)
, function(
terminal(split<0>)
, terminal(0)
)
)
)
, function(
terminal(split<0>)
, multiplies(
terminal(0)
, function(
terminal(split<0>)
, minus(
terminal(0)
, terminal(0)
)
)
)
)
)

plus(
plus(
terminal(0)
, function(
terminal(split<0>)
, function(
terminal(split<1>)
, terminal(0)
)
)
)
, function(
terminal(split<2>)
, multiplies(
terminal(0)
, function(
terminal(split<3>)
, minus(
terminal(0)
, terminal(0)
)
)
)
)
)

Press any key to continue . . .

reply