vector.cpp

来自「Boost provides free peer-reviewed portab」· C++ 代码 · 共 230 行

CPP
230
字号
//[ Vector/////////////////////////////////////////////////////////////////////////////////  Copyright 2008 Eric Niebler. Distributed under the Boost//  Software License, Version 1.0. (See accompanying file//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)//// This is an example of using BOOST_PROTO_DEFINE_OPERATORS to proto-ify// expressions using std::vector<>, a non-proto type. It is a port of the// Vector example from PETE (http://www.codesourcery.com/pooma/download.html).#include <vector>#include <iostream>#include <stdexcept>#include <boost/xpressive/proto/proto.hpp>#include <boost/xpressive/proto/debug.hpp>#include <boost/xpressive/proto/context.hpp>using namespace boost;using proto::_;template<typename Expr>struct VectorExpr;// Here is an evaluation context that indexes into a std::vector// expression and combines the result.struct VectorSubscriptCtx{    VectorSubscriptCtx(std::size_t i)      : i_(i)    {}    // Unless this is a vector terminal, use the    // default evaluation context    template<typename Expr, typename Arg = typename proto::result_of::arg<Expr>::type>    struct eval      : proto::default_eval<Expr, VectorSubscriptCtx const>    {};    // Index vector terminals with our subscript.    template<typename Expr, typename T, typename A>    struct eval<Expr, std::vector<T, A> >    {        typedef T result_type;        T operator ()(Expr &expr, VectorSubscriptCtx const &ctx) const        {            return proto::arg(expr)[ctx.i_];        }    };    std::size_t i_;};// Here is an evaluation context that verifies that all the// vectors in an expression have the same size.struct VectorSizeCtx{    VectorSizeCtx(std::size_t size)      : size_(size)    {}    // Unless this is a vector terminal, use the    // null evaluation context    template<typename Expr, typename Arg = typename proto::result_of::arg<Expr>::type>    struct eval      : proto::null_eval<Expr, VectorSizeCtx const>    {};    // Index array terminals with our subscript. Everything    // else will be handled by the default evaluation context.    template<typename Expr, typename T, typename A>    struct eval<Expr, std::vector<T, A> >    {        typedef void result_type;        result_type operator ()(Expr &expr, VectorSizeCtx const &ctx) const        {            if(ctx.size_ != proto::arg(expr).size())            {                throw std::runtime_error("LHS and RHS are not compatible");            }        }    };    std::size_t size_;};// A grammar which matches all the assignment operators,// so we can easily disable them.struct AssignOps  : proto::switch_<struct AssignOpsCases>{};// Here are the cases used by the switch_ above.struct AssignOpsCases{    template<typename Tag, int D = 0> struct case_  : proto::not_<_> {};    template<int D> struct case_< proto::tag::plus_assign, D >         : _ {};    template<int D> struct case_< proto::tag::minus_assign, D >        : _ {};    template<int D> struct case_< proto::tag::multiplies_assign, D >   : _ {};    template<int D> struct case_< proto::tag::divides_assign, D >      : _ {};    template<int D> struct case_< proto::tag::modulus_assign, D >      : _ {};    template<int D> struct case_< proto::tag::shift_left_assign, D >   : _ {};    template<int D> struct case_< proto::tag::shift_right_assign, D >  : _ {};    template<int D> struct case_< proto::tag::bitwise_and_assign, D >  : _ {};    template<int D> struct case_< proto::tag::bitwise_or_assign, D >   : _ {};    template<int D> struct case_< proto::tag::bitwise_xor_assign, D >  : _ {};};// A vector grammar is a terminal or some op that is not an// assignment op. (Assignment will be handled specially.)struct VectorGrammar  : proto::or_<        proto::terminal<_>      , proto::and_<proto::nary_expr<_, proto::vararg<VectorGrammar> >, proto::not_<AssignOps> >    >{};// Expressions in the vector domain will be wrapped in VectorExpr<>// and must conform to the VectorGrammarstruct VectorDomain  : proto::domain<proto::generator<VectorExpr>, VectorGrammar>{};// Here is VectorExpr, which extends a proto expr type by// giving it an operator [] which uses the VectorSubscriptCtx// to evaluate an expression with a given index.template<typename Expr>struct VectorExpr  : proto::extends<Expr, VectorExpr<Expr>, VectorDomain>{    explicit VectorExpr(Expr const &expr)      : proto::extends<Expr, VectorExpr<Expr>, VectorDomain>(expr)    {}    // Use the VectorSubscriptCtx to implement subscripting    // of a Vector expression tree.    typename proto::result_of::eval<Expr const, VectorSubscriptCtx const>::type    operator []( std::size_t i ) const    {        VectorSubscriptCtx const ctx(i);        return proto::eval(*this, ctx);    }};// Define a trait type for detecting vector terminals, to// be used by the BOOST_PROTO_DEFINE_OPERATORS macro below.template<typename T>struct IsVector  : mpl::false_{};template<typename T, typename A>struct IsVector<std::vector<T, A> >  : mpl::true_{};namespace VectorOps{    // This defines all the overloads to make expressions involving    // std::vector to build expression templates.    BOOST_PROTO_DEFINE_OPERATORS(IsVector, VectorDomain)    typedef VectorSubscriptCtx const CVectorSubscriptCtx;    // Assign to a vector from some expression.    template<typename T, typename A, typename Expr>    std::vector<T, A> &assign(std::vector<T, A> &arr, Expr const &expr)    {        VectorSizeCtx const size(arr.size());        proto::eval(proto::as_expr<VectorDomain>(expr), size); // will throw if the sizes don't match        for(std::size_t i = 0; i < arr.size(); ++i)        {            arr[i] = proto::as_expr<VectorDomain>(expr)[i];        }        return arr;    }    // Add-assign to a vector from some expression.    template<typename T, typename A, typename Expr>    std::vector<T, A> &operator +=(std::vector<T, A> &arr, Expr const &expr)    {        VectorSizeCtx const size(arr.size());        proto::eval(proto::as_expr<VectorDomain>(expr), size); // will throw if the sizes don't match        for(std::size_t i = 0; i < arr.size(); ++i)        {            arr[i] += proto::as_expr<VectorDomain>(expr)[i];        }        return arr;    }}int main(){    using namespace VectorOps;    int i;    const int n = 10;    std::vector<int> a,b,c,d;    std::vector<double> e(n);    for (i = 0; i < n; ++i)    {        a.push_back(i);        b.push_back(2*i);        c.push_back(3*i);        d.push_back(i);    }    VectorOps::assign(b, 2);    VectorOps::assign(d, a + b * c);    a += if_else(d < 30, b, c);    VectorOps::assign(e, c);    e += e - 4 / (c + 1);    for (i = 0; i < n; ++i)    {        std::cout            << " a(" << i << ") = " << a[i]            << " b(" << i << ") = " << b[i]            << " c(" << i << ") = " << c[i]            << " d(" << i << ") = " << d[i]            << " e(" << i << ") = " << e[i]            << std::endl;    }}//]

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?