codepad
[
create a new paste
]
login
|
about
Language:
C
C++
D
Haskell
Lua
OCaml
PHP
Perl
Plain Text
Python
Ruby
Scheme
Tcl
#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); }
Private
[
?
]
Run code
Submit