
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