[ create a new paste ] login | about

Link: http://codepad.org/ddjFylti    [ raw code | fork ]

C++, pasted on Jun 22:
#include <vector>
#include <iostream>

using namespace std;

#include <boost/proto/proto.hpp>
#include <boost/type_traits/is_arithmetic.hpp>

namespace nt2 { namespace containers
{
  //////////////////////////////////////////////////////////////////////////////
  // Main container expression class
  //////////////////////////////////////////////////////////////////////////////
  template< class Expression
          , class Category
          , class Tag   = typename Expression::proto_tag
          , class Dummy = boost::proto::is_proto_expr
          > class expr;


} }

namespace nt2 { namespace meta
{
  ////////////////////////////////////////////////////////////////////////////
  /// Proto grammar gathering 'low level' C++ operators
  ////////////////////////////////////////////////////////////////////////////
  template<class Grammar>
  struct low_level
       : boost::proto::or_< boost::proto::address_of<Grammar>
                          , boost::proto::dereference<Grammar>
                          > {};
} }

namespace nt2 { namespace containers
{
  // Container grammmar
  struct grammar
    : boost::proto::                // to change to proper block<_,_> type
      or_ < boost::proto::terminal< std::vector<boost::proto::_,boost::proto::_> >
          , boost::proto::and_< boost::proto::terminal<boost::proto::_>
                              , boost::proto::
                                if_<boost::is_arithmetic<boost::proto::_value>()>
                              >
          , boost::proto::and_< boost::proto ::nary_expr< boost::proto::_
                                                        , boost::proto::
                                                          vararg< grammar >
                                                        >
                              , boost::proto::not_< meta::low_level<boost::proto::_> >
                              >
          > {};

  //////////////////////////////////////////////////////////////////////////////
  // Container expression generator
  // A container expression bear its category and tag in its type for
  // overloading purpose
  //////////////////////////////////////////////////////////////////////////////
  template<class Category> struct generator
  {
    template<class Sig> struct result;

    template<class This, class X>
    struct result<This(X)>  { typedef expr<X,Category>  type; };

    template<class X> inline typename result<generator(X)>::type const
    operator()(X const &xpr) const
    {
      typename result<generator(X)>::type const that(xpr);
      return that;
    }
  };

  ////////////////////////////////////////////////////////////////////////////////
  // Container expression domain
  ////////////////////////////////////////////////////////////////////////////////
  template<class Category>
  struct domain : boost::proto::domain< generator<Category>
                                      , grammar
                                      , typename Category::parent_domain
                                      > {};
} }

namespace nt2 { namespace meta
{
  template<class Tag> struct is_assignment_operator : boost::mpl::false_ {};

  #define NT2_REGISTER_ASSIGNMENT_OPERATOR(TAG)                         \
  template<> struct is_assignment_operator<TAG> : boost::mpl::true_ {}  \
  /**/

  // Those tags invalidate the evaluation of their children
  NT2_REGISTER_ASSIGNMENT_OPERATOR(boost::proto::tag::comma              );
  NT2_REGISTER_ASSIGNMENT_OPERATOR(boost::proto::tag::assign             );
  NT2_REGISTER_ASSIGNMENT_OPERATOR(boost::proto::tag::plus_assign        );
  NT2_REGISTER_ASSIGNMENT_OPERATOR(boost::proto::tag::minus_assign       );
  NT2_REGISTER_ASSIGNMENT_OPERATOR(boost::proto::tag::multiplies_assign  );
  NT2_REGISTER_ASSIGNMENT_OPERATOR(boost::proto::tag::divides_assign     );
  NT2_REGISTER_ASSIGNMENT_OPERATOR(boost::proto::tag::modulus_assign     );
  NT2_REGISTER_ASSIGNMENT_OPERATOR(boost::proto::tag::bitwise_and_assign );
  NT2_REGISTER_ASSIGNMENT_OPERATOR(boost::proto::tag::bitwise_or_assign  );
  NT2_REGISTER_ASSIGNMENT_OPERATOR(boost::proto::tag::bitwise_xor_assign );
  NT2_REGISTER_ASSIGNMENT_OPERATOR(boost::proto::tag::shift_left_assign  );
  NT2_REGISTER_ASSIGNMENT_OPERATOR(boost::proto::tag::shift_right_assign );
} }

namespace nt2 { namespace containers
{
  ////////////////////////////////////////////////////////////////////////////////
  // Container expression
  // take care of building container AST and handle their evaluation
  ////////////////////////////////////////////////////////////////////////////////
  template<class X, class C, class Tag, class Dummy>
  struct expr : boost::proto::extends<X, expr<X, C, Tag>, domain<C> >
  {
    typedef C                                                   nt2_category_tag;
    typedef boost::proto::extends<X, expr<X,C,Tag>, domain<C> > base_type;

    explicit expr(X const &expr = X()) : base_type(expr), mEnabler(true)
    {
      enable(typename meta::is_assignment_operator<Tag>::type() );
    }

    ~expr()
    {
      eval( typename meta::is_assignment_operator<Tag>::type() );
    }

    protected:
    ////////////////////////////////////////////////////////////////////////////
    // if the expression is an assignment, prevent children multi-evaluation
    ////////////////////////////////////////////////////////////////////////////
    void enable( boost::mpl::true_ const&)
    {
      boost::proto::right(*this).mEnabler =
      boost::proto::left(*this).mEnabler  = false;
    }

    ////////////////////////////////////////////////////////////////////////////
    // if the expression is an assignment, start the numeric evaluation
    ////////////////////////////////////////////////////////////////////////////
    void eval( boost::mpl::true_ const&)
    {
      if(mEnabler) boost::proto::display_expr(*this);
    }

    ////////////////////////////////////////////////////////////////////////////
    // if the expression is not an assignment, then we don't have anything to do
    ////////////////////////////////////////////////////////////////////////////
    void enable( boost::mpl::false_ const&) {}
    void eval( boost::mpl::false_ const&)   {}

    public:
    mutable bool mEnabler;
  };

  template<class T,class Category> struct facade
  {
    typedef typename boost::proto::terminal< std::vector<T> >::type terminal_type;
    typedef expr<terminal_type, Category>                          type;
  };

  struct table_tag
  {
    typedef boost::proto::default_domain parent_domain;
  };

  template<class T>
  struct  table : public facade<T,table_tag>::type
  {
    typedef typename facade<T,table_tag>::type parent;

    BOOST_PROTO_EXTENDS_USING_ASSIGN(parent)
  };

  struct vector_tag
  {
    typedef domain<table_tag> parent_domain;
  };

  template<class T>
  struct  vector : public facade<T,vector_tag>::type
  {
    typedef typename facade<T,vector_tag>::type parent;

    BOOST_PROTO_EXTENDS_USING_ASSIGN(parent)
  };
} }

namespace nt2 { using containers::table;  }
namespace nt2 { using containers::vector; }

namespace nt2
{
  struct iota_ {};

  template<class B, class S,class E>
  struct iota_value
  {
    typedef B begin_type;
    typedef S step_type;
    typedef E end_type;
    B begin;
    S step;
    E end;
  };

  template<class I0,class I1>
  typename boost::proto
  ::result_of::make_expr< iota_
                        , containers::domain<containers::table_tag>
                        , iota_value<I0,int,I1>
                        >::type const
  iota( I0 const& begin, I1 const& end )
  {
    iota_value<I0,int,I1> that ={begin,1,end};
    return boost::proto::make_expr<iota_, containers::domain<containers::table_tag> >(that);
  }
}
int main()
{
  nt2::table<int> t;
  nt2::vector<int> x,y;

   t = t + nt2::iota(0,5);
}


Create a new paste based on this one


Comments: