|
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