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/proto/core.hpp>#include <boost/proto/context.hpp>namespace mpl = boost::mpl;namespace proto = boost::proto;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::value<Expr>::type::value_type result_type; result_type operator ()( Expr const & expr, lazy_subscript_context & ctx ) const { return proto::value( 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::value(*this).size(); for(std::size_t i = 0; i < size; ++i) { proto::value(*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 + -
显示快捷键?