For my problem, see this Stack Overflow question: https://stackoverflow.com/questions/49577746/is-there-standard-c-template-class-for-variable-length-arrays-with-maximum-siz
I need an array that stores its elements inline in the C++ language. The array must be variable-sized but up to the specified maximum. Most such arrays are small, thus it would be a waste on 64-bit architectures to use size_t as the array size everywhere. The code is here:
#include <stdexcept>
#include <algorithm>
#include <stdlib.h>
template<class C, class sz_t, sz_t maxsz> class inlinearray {
private:
typedef C value_type;
typedef value_type *pointer;
typedef const value_type *const_pointer;
typedef value_type &reference;
typedef const value_type &const_reference;
typedef value_type *iterator;
typedef const value_type *const_iterator;
typedef sz_t size_type;
typedef std::ptrdiff_t difference_type;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
sz_t sz;
union {
C realarray[maxsz]; // for correct alignment
char array[maxsz*sizeof(C)];
};
public:
inlinearray()
{
sz = 0;
}
~inlinearray(void)
{
clear();
}
void clear(void)
{
sz_t i;
for (i = 0; i < sz; i++)
{
data()[i].~C();
}
sz = 0;
}
template<class sz2_t, sz2_t maxsz2> inlinearray(inlinearray<C,sz2_t,maxsz2> that)
{
size_t i;
sz = that.sz;
for (i = 0; i < sz; i++)
{
push_back(that[i]);
}
}
template<class sz2_t, sz2_t maxsz2> void operator=(inlinearray<C,sz2_t, maxsz2> val2)
{
swap(val2);
}
void fill(const C& val)
{
std::fill_n(begin(), size(), val);
}
C &operator[](sz_t i) noexcept
{
return data()[i];
}
constexpr const C &operator[](sz_t i) const noexcept
{
return data()[i];
}
C at(sz_t i)
{
if (i >= sz)
{
throw std::out_of_range("inlinerray::at() out of range");
}
return data()[i];
}
constexpr const C at(sz_t i) const
{
if (i >= sz)
{
throw std::out_of_range("inlinerray::at() out of range");
}
return data()[i];
}
void push_back(const C &c)
{
if (sz >= maxsz)
{
abort();
}
new (data()+sz) C(c);
sz++;
}
void pop_back() noexcept
{
data()[sz-1].~C();
sz--;
}
template <class sz2_t, sz2_t maxsz2> void swap(inlinearray<C, sz2_t, maxsz2> &that)
{
if (that.sz > maxsz)
{
abort();
}
if (sz > that.maxsz)
{
abort();
}
std::swap_ranges(begin(), end(), that.begin());
std::swap(sz, that.sz);
}
constexpr sz_t size(void) const noexcept { return sz; }
constexpr sz_t max_size(void) const noexcept { return maxsz; }
constexpr bool empty() const noexcept { return sz == 0; }
C *begin() noexcept { return data(); }
C &front() noexcept { return data()[0]; }
C &back() noexcept { return sz == 0 ? data()[0] : data()[sz - 1]; }
constexpr const C &back() const noexcept { return sz == 0 ? data()[0] : data()[sz - 1]; }
C *end() noexcept { return data() + sz; }
C* data() noexcept { return reinterpret_cast<C*>(array); }
const C* data() const noexcept { return reinterpret_cast<const C*>(array); }
const C *begin() const noexcept { return data(); }
const C *end() const noexcept { return data() + sz; }
const C *cbegin() const noexcept { return data(); }
const C *cend() const noexcept { return data() + sz; }
reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
};
Now, is there something I should improve in this code? One obvious improvement would be to add support for larger "remote" data stored via a pointer to an array to make the maximum size unbounded.
I'm not very familiar with C++ (being mostly a C programmer), so I might not be aware of all of the language features and quirks.