/* * 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 */ #pragma once #include "../iterator.hpp" #include #include namespace cruft { /// A runtime-sizable array with a capacity fixed at compile-time. template 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 init): m_size (init.size ()) { CHECK_LE (init.size (), CapacityV); for (auto &&[idx, src]: cruft::izip (init)) m_data.objects[idx] = std::move (src); } template 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 remain (void) const noexcept { return capacity () - size (); } 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; }; //------------------------------------------------------------------------- template < std::size_t SizeA, typename ValueA, std::size_t SizeB, typename ValueB > constexpr auto operator== ( darray const &a, darray const &b ) { return std::equal ( a.begin (), a.end (), b.begin (), b.end () ); } //------------------------------------------------------------------------- template < std::size_t SizeA, typename ValueA, std::size_t SizeB, typename ValueB > constexpr auto operator!= ( darray const &a, darray const &b ) { return !(a == b); } }