#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::_;
template<typename Expr>
struct lazy_vector_expr;
struct LazyVectorGrammar
: proto::or_<
proto::terminal< std::vector<_> >
, proto::plus< LazyVectorGrammar, LazyVectorGrammar >
, proto::minus< LazyVectorGrammar, LazyVectorGrammar >
>
{};
struct lazy_vector_domain
: proto::domain<proto::generator<lazy_vector_expr>, LazyVectorGrammar>
{};
template<typename Size = std::size_t>
struct lazy_subscript_context
{
lazy_subscript_context(Size subscript)
: subscript_(subscript)
{}
template<typename Expr, typename Tag = typename Expr::proto_tag>
struct eval
: proto::default_eval<Expr, lazy_subscript_context>
{};
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_;
};
template<typename Expr>
struct lazy_vector_expr
: proto::extends<Expr, lazy_vector_expr<Expr>, lazy_vector_domain>
{
lazy_vector_expr( Expr const & expr = Expr() )
: lazy_vector_expr::proto_extends( expr )
{}
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);
}
};
template< 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 ) ) )
{}
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;
}
};
int main()
{
lazy_vector< double > v1( 4, 1.0 ), v2( 4, 2.0 ), v3( 4, 3.0 );
double d1 = ( v2 + v3 )[ 2 ]; std::cout << d1 << std::endl;
v1 += v2 - v3; std::cout << '{' << v1[0] << ',' << v1[1]
<< ',' << v1[2] << ',' << v1[3] << '}' << std::endl;
return 0;
}