Boost logo

Boost :

From: Eric Niebler (eric_at_[hidden])
Date: 2007-04-07 10:49:33


Andreas Pokorny wrote:
> Hi,
>
> I have looked at the examples and they all look very readable. I am now
> missing a facility to make more extended checks.
>
> I am not sure if I completly understood the syntax of the proto dsl.
> Here is a small matrix-vector example:
>
> struct RowVector
> : proto::or_<
> proto::terminal< row_vector<_> >
> , proto::terminal< dyn_row_vector >
> >{};
>
> struct ColumnVector
> : proto::or_<
> proto::terminal< col_vector<_> >
> , proto::terminal< dyn_col_vector >
> >{};
>
> struct MatrixExpr
> : proto::or_<
> proto::multiply<ColumnVector,RowVector>
> >{};
>
> struct ScalarExpr
> : proto::or_<
> proto::terminal< float>
> , proto::multiply<RowVector,ColumnVector>
> >{};
>
> In this case col_vector and row_vector could be like boost_array, with
> a compile time dimension, while dyn_col_vector and dyn_row_vector behave
> more like std::vector.
>
> Now I would like to forbid the mulitplication operator at compile time
> if both dimensions are compile time ones, and do not match. In all other
> cases the check has to be executed during runtime.
>
> How can I do that with proto?

I would create a predicate like dim_equal_to, like this:

template<typename A, typename B>
struct dim_equal_to
   : mpl::or_<
         mpl::equal_to<A,B>
       , mpl::equal_to<A,long_<-1> >
       , mpl::equal_to<B,long_<-1> >
>
{};

template<typename T>
struct dim_of;

template<typename Dim> // Assumes Dim is mpl::long_<N>
struct dim_of<row_vector<Dim> >
   : Dim
{};

template<typename Dim> // Assumes Dim is mpl::long_<N>
struct dim_of<col_vector<Dim> >
   : Dim
{};

template<typename T>
struct dim_of<dyn_row_vector>
   : long_<-1>
{};

template<typename T>
struct dim_of<dyn_col_vector>
   : long_<-1>
{};

And I would change MatrixExpr to look something like (untested!):

struct MatrixExpr
  : proto::and_<
      proto::multiply<ColumnVector,RowVector>
    , proto::if_<
        dim_equal_to<
          dim_of<
            proto::result_of::arg<proto::result_of::left<mpl::_> >
>
        , dim_of<
            proto::result_of::arg<proto::result_of::right<mpl::_> >
>
>
>
>
{};

ScalarExpr would get a similar treatment.

Some observations. In your code, you have:

> struct MatrixExpr
> : proto::or_<
> proto::multiply<ColumnVector,RowVector>
> >{};

In this case, the proto::or_ is superfluous, and can just be removed.
And in this expression:

> proto::terminal< row_vector<_> >

note that the _ is proto::_, not mpl::_, and that it will only match
types, not integers. Hence the comment above about assuming that Dim is
mpl::long_<N>.

HTH,

(I'm leaving today for a week-long vacation. I'll be on email only off
and on. Sorry 'bout that.)

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

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk