Boost logo

Boost Users :

From: Eric Niebler (eric_at_[hidden])
Date: 2007-12-07 22:26:12


AJD wrote:
> Hi,
>
> I've been trying out boost.proto lately and I've noticed that for my
> expressions it tends to force my operands to be created on the stack.
<snip>

The way you were defining your vector terminals confused proto into
thinking they needed to be wrapped in your vector_expr wrapper. The
extra layer of indirection is what is flummoxing msvc's optimizer. I can
only assume you went through those contortions in order to preserve the
nice aggregate initialization for your vector terminals. Try the
following instead.

#include <cstddef>
#include <iostream>
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/proto/context.hpp>
using namespace boost;

// This grammar describes which lazy vector expressions
// are allowed; namely, vector terminals and addition
// and subtraction of lazy vector expressions.
struct VectorGrammar
   : proto::or_<
         proto::and_<
             proto::terminal< proto::_ >
           , proto::if_< is_array<proto::result_of::arg<mpl::_> > >
>
       , proto::plus< VectorGrammar, VectorGrammar >
>
{};

// Expressions in the lazy vector domain must conform
// to the lazy vector grammar
struct VectorDomain;

// Here is an evaluation context that indexes into a lazy vector
// expression, and combines the result.
struct subscript_context
{
     subscript_context(std::size_t i) : i(i)
     {
     }

     // Use default_eval for all the operations ...
     template< typename Expr, typename Tag = typename Expr::proto_tag >
     struct eval : proto::default_eval< Expr, subscript_context const >
     {
     };

     // ... except for terminals, which we index with our subscript
     template< typename Expr >
     struct eval< Expr, proto::tag::terminal >
     {
         typedef typename Expr::value_type result_type;

         result_type operator ()(Expr const & expr, subscript_context
const & ctx) const
         {
             return proto::arg(expr)[ctx.i];
         }
     };
private:
     std::size_t i;
};

// Here is the domain-specific expression wrapper, which overrides
// operator [] to evaluate the expression using the subscript_context.
template< typename Expr >
struct vector_expr
{
     BOOST_PROTO_EXTENDS(Expr, vector_expr<Expr>, VectorDomain)

     // Use the subscript_context to implement subscripting
     // of a lazy vector expression tree.
     typename proto::result_of::eval< Expr, subscript_context const >::type
     operator [](std::size_t i) const
     {
         subscript_context const ctx(i);
         return proto::eval(*this, ctx);
     }
};

template< typename T, typename U = proto::is_proto_expr >
struct vector2;

template< typename T >
struct vector2<T[3]>
{
     BOOST_PROTO_EXTENDS(typename proto::terminal<T[3]>::type,
vector2<T[3]>, VectorDomain)

     typedef T value_type;

     T & operator [](std::size_t i)
     {
         return proto::arg(*this)[i];
     }

     T const & operator [](std::size_t i) const
     {
         return proto::arg(*this)[i];
     }
};

// Tell proto that in the VectorDomain, all
// expressions should be wrapped in vector_expr<>
struct VectorDomain
   : proto::domain<
         proto::pod_generator< vector_expr >
       , VectorGrammar
>
{
};

int main()
{
     vector2< float[3] > v1 = { 0, 1, 2 };
     vector2< float[3] > v2 = { 3, 4, 5 };
     vector2< float[3] > v3 = { 6, 7, 8 };

     // Add two vectors lazily and get the 2nd element.
     std::cout << (v1 + v2)[0];

     return 0;
}

For me, the line "std::cout << (v1 + v2)[0]" generates:

; 107 : // Add two vectors lazily and get the 2nd element.
; 108 : std::cout << (v1 + v2)[0];

        fldz
        push ecx
        fadd QWORD PTR __real_at_4008000000000000
        fstp DWORD PTR tv227[esp+12]
        fld DWORD PTR tv227[esp+12]
        fstp DWORD PTR [esp]
        call ??6?$basic_ostream_at_DU?$char_traits_at_D@std@@@std@@QAEAAV01_at_M@Z ;
std::basic_ostream<char,std::char_traits<char> >::operator<<

That looks pretty good to me.

HTH,

-- 
Eric Niebler
Boost Consulting
www.boost-consulting.com

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net