tags:

views:

179

answers:

2

I'm looking for a C++ container that's a cross between boost::array, boost::scoped_array and std::vector.

I want an array that's dynamically allocated via new[] (no custom allocators), contained in a type that has a meaningful copy-constructor.

boost::array is fixed-size, and although I don't need to resize anything, I don't know the size of the array at compile time.

boost::scoped_array doesn't have a copy constructor, and that means that I need to manually add one to each and every class using std::copy (my previous copy-paste intensive solution). This is also error prone, since you better make sure when you add a field that you added the correct initializer to the custom copy constructor; i.e. loads of boilerplate.

std::vector uses some pre-allocation system, and thus does not use operator new[]. This is problematic since it requires custom allocators, and worse, even that's not quite enough since there are some odd corner cases (which I don't fully understand) where return-by-value semantics are concerned that cause problems; I don't want the container to do anything fancy but simply contain a new[]'d array and copy it in it's copy constructor - and preferably overload all the usual suspects to be usable as a collection.

I don't need to resize anything, but the size must be controllable at runtime. Basically, a variant of scoped_array that happens to have a sane copy-constructor (for instance via std::copy) would be fine. Is there a standard collection for something like this?

Basically, I'm looking for a bog-standard dynamically allocated array with value semantics.

+1  A: 

Doesn't sound hard to write. Something along the lines of this?

template <typename T> my_array {
    T* m_ptr;
    size_t m_size;
public:
    my_array(size_t sz)
        : m_ptr(new T[sz])
        , m_size(sz)
    {}
    my_array(const my_array &other)
        : m_ptr(new T[other.m_size])
        , m_size(other.m_size)
    {
        std::copy(other.m_ptr, other.m_ptr + other.m_size, m_ptr);
    }
    ~my_array() {
        delete[] m_ptr;
    }

    // ... operator[], etc.
};

Usual disclaimers - this is off the top of my head, has not been compiled or anything.

Neil Gall
very nice, some people just dont' realise rolling your own is the best solution sometimes.
Matt Joiner
minor thing: add explicit to the first constructor. Otherwise `my_array a; a = 5;` is valid code...
sbk
The very problem of this approach of course, is to then write the iterators. By the way, there is a leak in your code and it will crash badly... hint: you did not define the Assignment Operator... and that's why some people just realize that rolling your own is often more complicated than first anticipated...
Matthieu M.
A minimal iterator could simpy be `typedef T* iterator; typedef const T* const_iterator` with corresponding begin and end methods.
UncleBens
Its also wrong. Please don't make this kind of suggestion unless you know how to do it. Copy Construtor. Assignment operator. Swap method. Copy and swap idium. Iterators. const correct iterators. Access to members etc etc etc.
Martin York
Read this for the basics. http://stackoverflow.com/questions/255612/c-dynamically-allocating-an-array-of-objects/255744#255744
Martin York
Yeah, and for exactly those reasons, I thought I'd avoid rolling my own - if a standard solution exists ;-).
Eamon Nerbonne
+1  A: 

Inherit privately from std::vector, and then adjust appropriately. For example remove resize(), and perhaps add setsize() and a bool flag to determine if the size has been set.

Your copy constructor can invoke the std::vector copy constructor, and set the flag automatically to prevent further changes.

Matt Joiner
Probably simpler not to allow any resizing methods at all, besides setting it in the constructor.
UncleBens
yeah, that's why i said to inherit privately. that way you have to explicity make members you want public.
Matt Joiner
Yeah, this sounds quite doable.
Eamon Nerbonne
Sometimes, just knowing what to look for helps:http://eigen.tuxfamily.org/api/StlContainers.htmlThis 'll get me where I want to, I'm sure, thanks!
Eamon Nerbonne