c – boost.proto在构建表达式树之前检测无效终端
发布时间:2020-12-16 07:32:00 所属栏目:百科 来源:网络整理
导读:我正在玩Boost.Proto,主要是为了好玩,看看将来我是否可以在我自己的项目中使用它.那说, 可能是这个库的大多数初学者,我玩过“懒惰矢量”示例的修改版本,但使用变换而不是上下文来执行评估.向量定义如下(好吧,我知道,’vector’对于在全局命名空间范围内定义
我正在玩Boost.Proto,主要是为了好玩,看看将来我是否可以在我自己的项目中使用它.那说,
可能是这个库的大多数初学者,我玩过“懒惰矢量”示例的修改版本,但使用变换而不是上下文来执行评估.向量定义如下(好吧,我知道,’vector’对于在全局命名空间范围内定义的东西不是一个好名字……) template <std::size_t D,class T> class vector { T data_[D]; enum { dimension = D }; // Constructors,destructors... }; // expression wrapper template <class> class vector_expr; 它是关于维度和数据类型的模板,boost :: array的种类(我没有使用它,因为我想重载operator =来接受表达式树,就像通常在这类事情中所做的那样).我使用proto手册中的代码定义了标量 // scalar = everything convertible to double struct scalar_terminal : proto::terminal<proto::convertible_to <double> > {}; // vector = everything for which the is_vector returns true_ template <class T> struct is_vector : mpl::false_ {}; template <std::size_t D,class T> struct is_vector <vector <D,T> > : mpl::true_ {}; struct vector_terminal : proto::and_ < proto::terminal<_>,proto::if_<is_vector<proto::_value>()> > {}; // domain struct vector_domain : proto::domain <proto::generator <vector_expr> > {}; // expression wrapper template <class Expr> struct vector_expr : proto::extends <Expr,vector_expr <Expr>,vector_domain> { typedef proto::extends <Expr,vector_domain> base_type; // Construct from expression (enough to compile) vector_expr (Expr const &e) : base_type (e) {} }; // Bring in operators BOOST_PROTO_DEFINE_OPERATORS(is_vector,vector_domain) 现在,我想要做的第一件事是:检查表达式中的所有向量终端是否都相同 // a meta-function that returns the vector dimension template <class T> struct vector_dim { typedef mpl::int_ <T::dimension> type; }; // a meta-function that combines dimensions from subtrees. int<-1> means // that sub-trees store vectors of differing static dimension. No good. template <class D1,class D2> struct dim_combine { typedef mpl::int_ < -1 > type; }; // ok,dimensions are the same,propagate up the value template <class D> struct dim_combine <D,D> { typedef D type; }; // 0 is used to mark scalars. It is ok to mix vectors and scalars // but propagate up the vector dimension only. This is for vector // on the left and scalar on the right. template <class D> struct dim_combine <D,mpl::int_ <0> > { typedef D type; }; // this is for scalar on the left,vector to the right of some // binary operator. template <class D> struct dim_combine <mpl::int_ <0>,D> { typedef D type; }; // need this too to avoid ambiguity between the two specializations // above when D is int_ <0>. Even if this combination should never // happen template <> struct dim_combine <mpl::int_ <0>,mpl::int_<0> > { typedef mpl::int_<0> type; }; // A transform that check that all arrays have the same dimension struct vec_dim_check : proto::or_ < proto::when < vector_terminal,vector_dim<proto::_value>() >,proto::when < scalar_terminal,boost::mpl::int_<0>() >,proto::when < proto::nary_expr<_,proto::vararg<_> >,proto::fold<_,boost::mpl::int_<0>(),dim_combine<vec_dim_check,proto::_state>()> > > {}; template <class E> void check_dim (E const&) { typedef typename boost::result_of<vec_dim_check(E)>::type type; BOOST_ASSERT(type::value == 3); } int main (int,char**) { vector <3,double> a,b,c; check_dim (2*a+b/c); return 0; } 问题是:由于数组的维度已经在表达式中编码,因此它应该 在此先感谢,最好的问候 解决方法
非常好.现在你需要定义一个只接受有效矢量表达式的语法,如下所示:
struct vector_grammar_untyped : proto::or_< scalar_terminal,vector_terminal,proto::nary_expr<proto::_,proto::vararg<vector_grammar_untyped> > > {}; struct vector_grammar : proto::and_< vector_grammar_untyped,proto::if_<mpl::not_equal_to< mpl::int_<-1>,vec_dim_check >()> > {}; 然后,您更改vector_domain的定义,如下所示: struct vector_domain : proto::domain <proto::generator <vector_expr>,vector_grammar > {}; 这应该使您无法创建不通过自定义类型检查的表达式. proto :: domain的第二个模板参数是该域中所有表达式必须符合的语法. 免责声明:上述代码未经测试,但它应该让您朝着正确的方向前进. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |