lazy_vector.cpp

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

CPP
145
字号
//[ LazyVector/////////////////////////////////////////////////////////////////////////////////  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 example constructs a mini-library for linear algebra, using// expression templates to eliminate the need for temporaries when// adding vectors of numbers.//// This example uses a domain with a grammar to prune the set// of overloaded operators. Only those operators that produce// valid lazy vector expressions are allowed.#include <vector>#include <iostream>#include <boost/mpl/int.hpp>#include <boost/xpressive/proto/proto.hpp>#include <boost/xpressive/proto/context.hpp>using namespace boost;using proto::_;// This grammar describes which lazy vector expressions// are allowed; namely, vector terminals and addition// and subtraction of lazy vector expressions.struct LazyVectorGrammar  : proto::or_<        proto::terminal< std::vector<_> >      , proto::plus< LazyVectorGrammar, LazyVectorGrammar >      , proto::minus< LazyVectorGrammar, LazyVectorGrammar >    >{};// Expressions in the lazy vector domain must conform// to the lazy vector grammarstruct lazy_vector_domain;// Here is an evaluation context that indexes into a lazy vector// expression, and combines the result.template<typename Size = std::size_t>struct lazy_subscript_context{    lazy_subscript_context(Size subscript)      : subscript_(subscript)    {}    // Use default_eval for all the operations ...    template<typename Expr, typename Tag = typename Expr::proto_tag>    struct eval      : proto::default_eval<Expr, lazy_subscript_context>    {};    // ... except for terminals, which we index with our subscript    template<typename Expr>    struct eval<Expr, proto::tag::terminal>    {        typedef typename proto::result_of::arg<Expr>::type::value_type result_type;        result_type operator ()( Expr const & expr, lazy_subscript_context & ctx ) const        {            return proto::arg( expr )[ ctx.subscript_ ];        }    };    Size subscript_;};// Here is the domain-specific expression wrapper, which overrides// operator [] to evaluate the expression using the lazy_subscript_context.template<typename Expr>struct lazy_vector_expr  : proto::extends<Expr, lazy_vector_expr<Expr>, lazy_vector_domain>{    typedef proto::extends<Expr, lazy_vector_expr<Expr>, lazy_vector_domain> base_type;    lazy_vector_expr( Expr const & expr = Expr() )      : base_type( expr )    {}    // Use the lazy_subscript_context<> to implement subscripting    // of a lazy vector expression tree.    template< typename Size >    typename proto::result_of::eval< Expr, lazy_subscript_context<Size> >::type    operator []( Size subscript ) const    {        lazy_subscript_context<Size> ctx(subscript);        return proto::eval(*this, ctx);    }};// Here is our lazy_vector terminal, implemented in terms of lazy_vector_exprtemplate< typename T >struct lazy_vector  : lazy_vector_expr< typename proto::terminal< std::vector<T> >::type >{    typedef typename proto::terminal< std::vector<T> >::type expr_type;    lazy_vector( std::size_t size = 0, T const & value = T() )      : lazy_vector_expr<expr_type>( expr_type::make( std::vector<T>( size, value ) ) )    {}    // Here we define a += operator for lazy vector terminals that    // takes a lazy vector expression and indexes it. expr[i] here    // uses lazy_subscript_context<> under the covers.    template< typename Expr >    lazy_vector &operator += (Expr const & expr)    {        std::size_t size = proto::arg(*this).size();        for(std::size_t i = 0; i < size; ++i)        {            proto::arg(*this)[i] += expr[i];        }        return *this;    }};// Tell proto that in the lazy_vector_domain, all// expressions should be wrapped in laxy_vector_expr<>struct lazy_vector_domain  : proto::domain<proto::generator<lazy_vector_expr>, LazyVectorGrammar>{};int main(){    // lazy_vectors with 4 elements each.    lazy_vector< double > v1( 4, 1.0 ), v2( 4, 2.0 ), v3( 4, 3.0 );    // Add two vectors lazily and get the 2nd element.    double d1 = ( v2 + v3 )[ 2 ];   // Look ma, no temporaries!    std::cout << d1 << std::endl;    // Subtract two vectors and add the result to a third vector.    v1 += v2 - v3;                  // Still no temporaries!    std::cout << '{' << v1[0] << ',' << v1[1]              << ',' << v1[2] << ',' << v1[3] << '}' << std::endl;    // This expression is disallowed because it does not conform    // to the LazyVectorGrammar    //(v2 + v3) += v1;    return 0;}//]

⌨️ 快捷键说明

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