I present my implementation of an HeapArray
and StackArray
.
Similar to the implementation of my ArrayView which justs open a window into sequence here a generic implementation of an actual sequence. I have to admit both classes(ArrayView and Stack/HeapArray) look very similar but they are supposed do to a very similar job, so i think that was not avoidable.
As always my aim was to avoid any runtime operation as far as possible, so that the compiler can resolve most of the code at compile-time, here in this particular case it is not as easy to follow this policy which lies in the nature of runtime allocation for the HeapArray
implemenation where the StackArray
can be resolved mostly at compiletime similar to std::array
.
Both classes have the same interface the only real difference is the way the array is allocated. The StackArray
allocates the requested array at compile-time as normal c-like array in the form of type Field[Size]
while HeapArray
handles the the array dynamically via the special overload oif std::unique_ptr<type[]>
. I am not sure if that is good or bad use of this specialization of std::unique_ptr
but i like the idea quite a lot not to use new/delete
myself in a direct manner. I could imagine this could be point of critic but maybe not.
As usual any criticism are welcome and is much appreciated.
You will find an code example at CompilerExplorer
The HeapArray:
template<typename T,std::size_t SIZE>
class HeapArray {
private:
std::unique_ptr<T[]> mField;
public:
using Self = HeapArray<T, SIZE>;
using value_type = T;
using pointer = value_type*;
using reference = value_type&;
using const_reference = value_type const&;
using iterator = value_type*;
using const_iterator = value_type const*;
template<typename ...Targs>
constexpr HeapArray(Targs... args)
: mField{std::make_unique<value_type[]>(sizeof...(Targs))}
//: mField{std::make_unique<value_type[]>(sizeof(value_type)*sizeof...(Targs))}
{
//If you know a better way of initialize this array please let me know
auto list = {args...};
auto iter = std::begin(list);
for(auto i = 0ull; i < SIZE;i++,std::next(iter))
{
mField[i] = *iter;
}
}
reference operator[](std::size_t index) {
return mField[index];
};
const_reference operator[](std::size_t index) const {
return mField[index];
};
reference at(std::size_t index) {
assert(index > SIZE);
return mField[index];
};
const_reference at(std::size_t index) const {
assert(index >SIZE);
return mField[index];
};
template<std::size_t Index>
constexpr value_type at() const {
static_assert(Index > SIZE, "Index out of bound");
return mField[Index];
}
constexpr pointer data() const { return mField; }
constexpr bool operator==(const Self& rhs) const noexcept {
for (int i = 0; i < SIZE; i++)
if (mField[i] != rhs.at(i)) return false;
return true;
};
constexpr bool operator<(const Self& rhs) const noexcept {
for (int i = 0; i < SIZE; i++)
if (mField[i] > rhs[i]) return false;
return true;
};
constexpr bool operator>(const Self& rhs)const noexcept {
for (int i = 0; i < SIZE; i++)
if (mField[i] < rhs[i]) return false;
return true;
};
constexpr bool operator<=(const Self& rhs) const noexcept {
for (int i = 0; i < SIZE; i++)
if (mField[i] >= rhs[i]) return false;
return true;
};
constexpr bool operator>=(const Self& rhs) const noexcept {
for (int i = 0; i < SIZE; i++)
if (mField[i] <= rhs[i]) return false;
return true;
};
constexpr iterator begin() noexcept { return (mField); }
constexpr iterator end() noexcept { return mField + SIZE; }
constexpr const_iterator begin() const noexcept { return (mField); }
constexpr const_iterator end() const noexcept { return mField + SIZE; }
constexpr const_iterator cbegin() const noexcept { return { mField }; }
constexpr const_iterator cend() const noexcept { return mField + SIZE; }
constexpr reference front() noexcept { return *mField; }
constexpr reference back() noexcept { return *(mField + SIZE - 1); }
constexpr const_reference cfront() const noexcept { return *mField; }
constexpr const_reference cback() const noexcept { return *(mField + SIZE - 1); }
constexpr const_iterator find_first_of(value_type data) const noexcept{
for (auto i = 0; i < SIZE; i++)
if (mField[i] == data)
return &mField[i];
return nullptr;
}
/*template<typename predicate>
auto find_all(predicate Functor) const noexcept{
static_assert(!std::is_function< decltype(Functor)>::value , "find_all() of 'HeapArray' expects as predicate a function!" );
GenericList<T> res;
for (auto i = 0u; i < SIZE; i++)
if (Functor(mField[i]))
res.addTail(mField[i]);
return res;
}*/
constexpr void fill(const_reference Value) noexcept{
for (auto& item : *this)
item = Value;
}
template<typename predicate>
constexpr void apply(predicate Functor) noexcept{
static_assert(!std::is_function< decltype(Functor)>::value, "apply() of 'HeapArray' expects as predicate a function!");
for (auto& item : *this)
Functor(item);
}
};
The StackArray:
template<typename T, std::size_t SIZE>
class StackArray {
private:
T mField[SIZE];
public:
using Self = StackArray<T, SIZE>;
using value_type = T;
using pointer = value_type*;
using reference = value_type&;
using const_reference = value_type const&;
using iterator = value_type*;
using const_iterator = value_type const*;
template<typename ...Targs>
constexpr StackArray(Targs... args) : mField{ std::forward<value_type>(args)... } {}
reference operator[](std::size_t index) {
return mField[index];
};
const_reference operator[](std::size_t index) const {
return mField[index];
};
reference at(std::size_t index) {
assert(index > SIZE);
return mField[index];
};
const_reference at(std::size_t index) const {
assert(index > size());
return mField[index];
};
template<std::size_t Index>
constexpr value_type at() const {
static_assert(Index > SIZE, "Index out of bound");
return mField[Index];
}
constexpr bool operator==(const Self& rhs) const noexcept {
for (int i = 0; i < SIZE; i++)
if (mField[i] != rhs.at(i)) return false;
return true;
};
constexpr bool operator<(const Self& rhs) const noexcept {
for (int i = 0; i < SIZE; i++)
if (mField[i] > rhs[i]) return false;
return true;
};
constexpr bool operator>(const Self& rhs)const noexcept {
for (int i = 0; i < SIZE; i++)
if (mField[i] < rhs[i]) return false;
return true;
};
constexpr bool operator<=(const Self& rhs) const noexcept {
for (int i = 0; i < SIZE; i++)
if (mField[i] >= rhs[i]) return false;
return true;
};
constexpr bool operator>=(const Self& rhs) const noexcept {
for (int i = 0; i < SIZE; i++)
if (mField[i] <= rhs[i]) return false;
return true;
};
constexpr pointer data() const { return mField; }
constexpr iterator begin() noexcept { return (mField); }
constexpr iterator end() noexcept { return mField + SIZE; }
constexpr const_iterator begin() const noexcept { return (mField); }
constexpr const_iterator end() const noexcept { return mField + SIZE; }
constexpr const_iterator cbegin() const noexcept { return { mField }; }
constexpr const_iterator cend() const noexcept { return mField + SIZE; }
constexpr reference front() noexcept { return *mField; }
constexpr reference back() noexcept { return *(mField + SIZE - 1); }
constexpr const_reference cfront() const noexcept { return *mField; }
constexpr const_reference cback() const noexcept { return *(mField + SIZE - 1); }
constexpr std::size_t size() const noexcept { return SIZE; }
constexpr std::size_t length() const noexcept { return SIZE; }
constexpr const_iterator find_first_of(value_type data) const noexcept {
for (auto i = 0; i < size(); i++)
if (mField[i] == data)
return &mField[i];
return nullptr;
}
/*template<typename predicate>
constexpr auto find_all(predicate Functor) noexcept {
static_assert(!std::is_function< decltype(Functor)>::value, "find_all() of 'StackArray' expects as predicate a function!");
GenericList<T> res;
for (auto i = 0u; i < size(); i++)
if (Functor(mField[i]))
res.addTail(mField[i]);
return res;
}*/
constexpr void fill(const_reference Value) noexcept {
for (auto& item : *this)
item = Value;
}
template<typename predicate>
constexpr void apply(predicate Functor) noexcept {
static_assert(!std::is_function< decltype(Functor)>::value, "apply() of 'StackArray' expects as predicate a function!");
for (auto& item : *this)
Functor(item);
}
};