Subject: Re: [boost] Try out a multi-dimensional adapter class template?
From: Daryle Walker (darylew_at_[hidden])
Date: 2013-10-08 20:39:58
> From: ramey_at_[hidden]
> Date: Tue, 8 Oct 2013 08:50:54 -0800
> Daryle Walker wrote:
> > I added a new class template for my library at
> > <https://github.com/CTMacUser/ArrayMD>. It's called "multiarray,"
> > and it's an adapter class like stack and queue. But the new
> > interface is only for accessing elements. Besides the element and
> > container types, the template header for the class takes the number
> > of dimensions. The class uses at, operator  and operator () to
> > access an element. It has methods to read/write the shape of the
> > array and the priority of each index. There are no methods to change
> > the number of elements stored; you have to either use a fixed-size
> > container or sub-class the multi-array to add methods to change the
> > size. (The container sub-object is protected, like the Standard
> > adapters.) I split the main code into two base class templates,
> > because the code for computing the offset from an index tuple and the
> > code for referencing an element were nearly distinct. This really
> > screws up my attempt at Doxygen comments. Any ideas? Or is my case
> > too complex for what Doxygen's author thought could be handled.
> I've looked at the document above. It would seem to me that this
> is similar or equivalent to boost.multi-array with extents set at
> compile time rather than at runtime. Is my understanding of this
> correct? If not how is it wrong.
Both templates get the number of dimensions as a compile-time parameter and the actual extent values at run-time. The Boost version can take the extents and priorities in the constructor, while my version has to change those attributes in separate call(s). But it seems that construction time is the only opportunity for the Boost version to use a different index priority; it can't be changed later, unlike mine.
The Boost version is a full container, including allocator support. There are also mutable and immutable view classes. My version is an adapter, and punts storage considerations into what container type is used. Since my version holds the container as a protected member, view classes are nonsensical.
The Boost version was designed during a time of broken C++98 support, while mine was designed for compliant C++11 support. The new version can take advantage of newer features. My version uses Standard classes to take indices and to get & set extents and priorities. The Boost version uses a lot of auxiliary classes. The Boost design is spread over many headers; my version is compact enough to be a done-in-one header (but it does less, too).
Neither version provides methods to directly change the number of elements. The Boost version can change its element count through its resize method. My version can't at all, except through derived classes. But my version decouples the elements stored and what's needed. You only crash when referencing an element beyond the container's bounds. It was designed with std::array as a base container. It should be efficient when the desired size stays close to the array's fixed size.
My version indexes only elements; sub-arrays are not supported. It wouldn't be efficient, since elements would not be contiguous in general. Create a new array object of the smaller size and use (c)apply to copy over what you want. Fancy indexing, outside of priorities, is not supported either. (Since there's no sub-arrays nor views, the chain-of-operator syntax is not supported.)
My original intention was to make the dimension count a run-time variable. This would necessitate dynamic containers for the extents and priorities, probably a smart-pointer in array mode. But reasoning the copying & moving semantics was too hard. It's easy with a fixed extent size, and I guess it'll be the most common case. (I separated the indexing and containment into separate base classes. I could make a new indexing base for dynamic dimensions while keeping the same containment base.)
> I've used multi-array on various occasions and have been struck> by how well it's done. (and better than average documented).
> Have you considered just augmentting multi-array with some
> constructors or "re-sizer" which use extents defined as template
> parameters? It seem that if you could do this, one would be able
> to leverage all that is done already. Even if this is not possible,
> it would be nice to have an interface as close as possible to
> mult-array to leverage on one's understanding of both libraries.
They have different interfaces. Neither of them can define the extent values at compile-time. Another class in that GitHub repository, array_md, does do that. However, it's a variadic extension of std::array, and so does not have any of the storage or indexing options that Boost.Multi-Array has. My multiarray adapter was started from so many complaints that array_md doesn't support anything besides row-major order, making it less desirable for all the math & science junkies that wanted column-major (or scrambled-priority) storage.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk