Boost logo

Boost :

From: Manfred Doudar (manfred.doudar_at_[hidden])
Date: 2005-11-16 06:23:32


Boosters:

I'm hoping someone here might be of help, and enlighten me
with some more MPL trickery ...

What I'm doing:

Have a class MyArray derived from blitz::Array, and among other
things, I'm trying to add the operator[] to slice through a
multi-dim array ... pretty much have it, with one
exception - once I get to applying [] on a
1-dimensional (linear) array, I of course expect a scalar,
but therein lies the problem - the compiler also
"sees" a 0-dimensional array (not good!), and that's where I run
into problems...

Brief snippets of code:

Please ignore the return by value for the moment - I can clean that
up later, not to mention the Boost PP extensions I can add.

Below is a cut-down class definition, and method implementation follows.

Class Declaration:
------------------

template <typename T, int Rank = 1>
class MyArray : public blitz::Array<T, boost::mpl::int_<Rank>::value>
{
public:

 // ... methods

};

(Partial Listing) Implementation:
---------------------------------

template <typename T, int Rank>
MyArray<T, Rank> :: Array(const blitz::Array<T,
                          boost::mpl::int_<Rank>::value>& btz
                         ) throw()
: blitz::Array<T, boost::mpl::int_<Rank>::value> (const_cast<T *>
(btz.data())
                                                   , btz.shape()
                                                   , blitz::duplicateData
                                                  )
{
    // Copy Ctor
}

template <typename T, int Rank>
void MyArray<T, Rank> :: getParamList(blitz::TinyVector<
                                          boost::variant<
                                            blitz::Range
                                          , blitz::nilArraySection
>
                                       , 2
>& plist
                                      )
{
  // Aides us in setting up the parameter list for slicing

  plist(boost::mpl::int_<0>::value) = blitz::Range::all();
  plist(boost::mpl::int_<1>::value) = blitz::nilArraySection();
}

/* Now, how do I get T out when Rank == 1, ... compiler complains
   about seeing a MyArray/blitz::Array of <T, Rank = 0>
   (, which is not defined for blitz Arrays)
*/
template <typename T, int Rank>
typename boost::mpl::if_
                         < typename boost::mpl::equal_to
                           < boost::mpl::int_<Rank>
                           , boost::mpl::int_<1>
>::type
                         , T
                         , blitz::Array<T,
                                  boost::mpl::int_<Rank>::prior::value>
>::type
MyArray<T, Rank> :: operator[] (const int& index) throw();
{
   // Slicing

   // this bit of indirection is useful
   blitz::TinyVector<boost::variant<blitz::Range,
                                    blitz::nilArraySection>, 2> plist;

   this->getParamList(plist);

/* pseudocode: (kind of) ****************

  return
     // cast for return type
     static_cast< (Rank == 1 ? T : MyArray<T, Rank - 1>) >
     (
         // cast _this_ ptr
         * static_cast<const blitz::Array<T, Rank> *> (this)

 // the blitz Array parameter list
(index, //the param list
 *boost::get<blitz::Range *or* blitz::nilArraySection>(&plist(0 *or* 1),
  ...
)
     )

  Sample usage:

    MyArray<float, 3> arr(btzArray);
    arr[10]; // gives MyArray<float, 2> out
    arr[10][2] // gives MyArray<float, 1> out
    arr[10][2][7] // expect a float to be output

********************/
  

  return static_cast< typename boost::mpl::if_<
                          typename boost::mpl::equal_to<
                             boost::mpl::int_<Rank>
                          , boost::mpl::int_<1>
>::type
                      , T
                      , MyArray<T, boost::mpl::int_<Rank>::prior::value>
>::type
>

          ((* static_cast<const blitz::Array<T,
               boost::mpl::int_<Rank>::value> *> (this))

 /* the parameter list */
 (index,
     *boost::get<
                   typename boost::mpl::if_<
                      typename boost::mpl::less<
                            boost::mpl::int_<1>
                          , boost::mpl::int_<Rank>
>::type
                      , blitz::Range
                      , blitz::nilArraySection
>::type
>

      (&plist(boost::mpl::if_<
                  typename boost::mpl::less<
                       boost::mpl::int_<1>
                     , boost::mpl::int_<Rank>
>::type
                  , boost::mpl::int_<0>
                  , boost::mpl::int_<1>
>::type::value
              )
       )

     /*
         , ... we can extend the parameter list with Boost.PP
     */
 );

*************

(Partial) Compiler Error Messages:
---------------------------------

   `boost::mpl::algo_::if_<boost::mpl::equal_to<boost::mpl::int_<Rank>,
   boost::mpl::int_<1> >::type, T, blitz::Array<T, typename
   boost::mpl::int_<Rank>::prior::value> >::type moe::Array<T,
   Rank>::operator[](const S&) [with S = int, T = int, int Rank = 1]':
arr.cc:172: instantiated from here
arr.cc:666: invalid static_cast from type `blitz::Array<int, 0>' to type
`int'
/usr/local/include/blitz/array/storage.h: In constructor
   `blitz::GeneralArrayStorage<N_rank>::GeneralArrayStorage() [with int
N_rank
   = 0]':

<snip ... more messages>

/usr/local/include/blitz/array/storage.h:60: no match for call to `(
   blitz::TinyVector<int, 0>) (int&)'

<snip ... more messages>

*******************

So ... can anyone tell me if what I'm trying to do is possible ?
Is there some MPL trickery to do it ?
The above does work up until I apply the operator[] on a 1-d linear
array.

Help and ideas would be appreciated.

Ah yes, using gcc 3.2.2,
and Boost version 1.31 (maybe 1.32) .. downloaded in August 2004
(yes, I know that's ancient - but managment can be a real pain sometimes)

P.S. tried to format this message as best I could, hope it's readable.

With Thanks,

-- 
Manfred Doudar
MetOcean Engineers
www.metoceanengineers.com

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