libcruft-util/array/darray.hpp

140 lines
3.8 KiB
C++

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2017 Danny Robson <danny@nerdcruft.net>
*/
#pragma once
#include "../iterator.hpp"
#include <iterator>
#include <cstddef>
namespace cruft {
/// A runtime-sizable array with a capacity fixed at compile-time.
template <std::size_t CapacityV, typename ValueT>
class darray {
public:
using value_type = ValueT;
using size_type = std::size_t;
static constexpr auto elements = CapacityV;
using pointer = ValueT*;
using const_pointer = ValueT const*;
using iterator = pointer;
using const_iterator = const_pointer;
darray (): m_size (0) { ; }
darray (darray const&) = default;
darray (darray &&) = default;
darray& operator= (darray const&) = default;
darray& operator= (darray &&) = default;
~darray ()
{
for (auto &i: *this)
i.~ValueT ();
}
darray (std::initializer_list<ValueT> init):
m_size (init.size ())
{
CHECK_LE (init.size (), CapacityV);
for (auto &&[src,dst]: cruft::zip (init, m_data.objects))
dst = std::move (src);
}
template <typename InputT>
darray (InputT first, InputT last):
darray ()
{
for ( ; first != last; ++first) {
CHECK_LT (m_size, CapacityV);
m_data.objects[m_size++] = *first;
}
}
ValueT& operator[] (std::size_t idx)& noexcept
{
CHECK_LT (idx, m_size);
return m_data.objects[idx];
}
ValueT const& operator[] (std::size_t idx) const& noexcept
{
CHECK_LT (idx, m_size);
return m_data.objects[idx];
}
iterator begin (void)& { return m_data.objects + 0; }
iterator end (void)& { return m_data.objects + m_size; }
const_iterator begin (void) const& { return m_data.objects + 0; }
const_iterator end (void) const& { return m_data.objects + m_size; }
decltype(auto) cbegin (void) const& { return begin (); }
decltype(auto) cend (void) const& { return end (); }
std::size_t size (void) const noexcept { return m_size; }
constexpr auto capacity (void) const noexcept { return CapacityV; }
constexpr bool empty (void) const noexcept { return !!m_size; }
constexpr bool full (void) const noexcept { return m_size == CapacityV; }
void erase (iterator pos)
{
CHECK_LIMIT (pos, begin (), end ());
for (auto cursor = pos + 1; cursor != end (); ++cursor)
*(cursor - 1) = std::move (*cursor);
--m_size;
}
void insert (iterator pos, ValueT const &val)
{
CHECK_LIMIT (pos, begin (), end ());
CHECK_LT (m_size, CapacityV);
*pos = val;
for (auto cursor = pos + 1; cursor != end (); ++cursor)
*cursor = *(cursor - 1);
}
iterator push_back (value_type const &val)&
{
CHECK_LT (m_size, CapacityV);
m_data.objects[m_size] = val;
return m_data.objects + m_size++;
}
iterator push_back (value_type &&val)&
{
CHECK_LT (m_size, CapacityV);
m_data.objects[m_size] = std::move (val);
return m_data.objects + m_size++;
}
private:
union alignas (ValueT) {
char store[sizeof (ValueT) * CapacityV];
ValueT objects[CapacityV];
} m_data;
std::size_t m_size;
};
}