darray: add a static capacity, dynamic sized array
This commit is contained in:
parent
ddb0e75962
commit
79edea8f2d
@ -215,6 +215,7 @@ list (
|
|||||||
alloc/raw/stack.cpp
|
alloc/raw/stack.cpp
|
||||||
alloc/raw/stack.hpp
|
alloc/raw/stack.hpp
|
||||||
annotation.hpp
|
annotation.hpp
|
||||||
|
array/darray.hpp
|
||||||
ascii.hpp
|
ascii.hpp
|
||||||
backtrace.hpp
|
backtrace.hpp
|
||||||
bezier.cpp
|
bezier.cpp
|
||||||
@ -515,6 +516,7 @@ if (TESTS)
|
|||||||
alloc/stack
|
alloc/stack
|
||||||
alloc/forwarding
|
alloc/forwarding
|
||||||
affine
|
affine
|
||||||
|
array/darray
|
||||||
backtrace
|
backtrace
|
||||||
bezier
|
bezier
|
||||||
bitwise
|
bitwise
|
||||||
|
131
array/darray.hpp
Normal file
131
array/darray.hpp
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
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 ()
|
||||||
|
{
|
||||||
|
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 auto empty (void) const noexcept { return !!m_size; }
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
}
|
34
test/array/darray.cpp
Normal file
34
test/array/darray.cpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#include <cruft/util/tap.hpp>
|
||||||
|
#include <cruft/util/array/darray.hpp>
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int, char**)
|
||||||
|
{
|
||||||
|
cruft::TAP::logger tap;
|
||||||
|
|
||||||
|
cruft::darray<8,int> val ({ 0, 1, 2, 3, 4, 5, 6, 7});
|
||||||
|
|
||||||
|
tap.expect_eq (val.size (), 8u, "query for size");
|
||||||
|
|
||||||
|
tap.expect_eq (val.capacity (), decltype(val)::elements, "static vs dynamic query for capacity");
|
||||||
|
|
||||||
|
{
|
||||||
|
auto const sum = std::accumulate (val.cbegin (), val.cend (), 0u);
|
||||||
|
tap.expect_eq (sum, 28u, "accumulate over initializer_list range");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
val.erase (val.begin () + 2);
|
||||||
|
tap.expect_eq (val.size (), 7u, "erasing removes one element");
|
||||||
|
|
||||||
|
auto const sum = std::accumulate (val.cbegin (), val.cend (), 0u);
|
||||||
|
tap.expect_eq (sum, 26u, "erase one element");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
val.insert (val.begin () + 4, 9);
|
||||||
|
tap.expect_eq (val[5], 9, "inserted values matches indexed value");
|
||||||
|
}
|
||||||
|
|
||||||
|
return tap.status ();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user