#pragma once #include #include #include #include "dxxsconf.h" #include "compiler-array.h" template class base_count_array_t { protected: typedef T size_type; typedef base_count_array_t base_type; void clear() { m_count = 0; } size_type m_count; public: size_type count() const { return m_count; } bool empty() const { return !m_count; } base_count_array_t() : m_count(0) {} }; template class count_array_t : public base_count_array_t<> { // typedef base_type::size_type size_type; public: typedef array array_type; typedef typename array_type::value_type value_type; typedef typename array_type::iterator iterator; typedef typename array_type::const_iterator const_iterator; typedef typename array_type::const_reference const_reference; static typename array_type::size_type size() { return S; } ~count_array_t() { clear(); } count_array_t &operator=(const count_array_t &rhs) { if (this != &rhs) { iterator lb = begin(); iterator le = end(); const_iterator rb = rhs.begin(); const_iterator re = rhs.end(); for (; lb != le && rb != re; ++lb, ++rb) *lb = *rb; shrink(lb); for (; rb != re; ++rb) emplace_back(*rb); } return *this; } template void emplace_back(Args&&... args) { if (m_count >= S) throw std::length_error("too many elements"); new(reinterpret_cast(&arrayref()[m_count])) T(std::forward(args)...); ++ m_count; } void clear() { shrink(begin()); } // for std::back_insert_iterator void push_back(const T& t) { emplace_back(t); } void pop_back() { shrink(end() - 1); } iterator begin() { return arrayref().begin(); } iterator end() { return arrayref().begin() + m_count; } iterator find(const T &t) { return std::find(begin(), end(), t); } const_iterator find(const T &t) const { return std::find(begin(), end(), t); } const_reference operator[](size_type i) const { if (i >= m_count) throw std::out_of_range("not enough elements"); return arrayref()[i]; } const_reference back() const { return (*this)[m_count - 1]; } bool contains(const T &t) const { return find(t) != end(); } void erase(iterator i) { shrink(i); } void erase(const T &t) { shrink(std::remove(begin(), end(), t)); } template void erase_if(F f) { shrink(std::remove_if(begin(), end(), f)); } void replace(const T &o, const T &n) { std::replace(begin(), end(), o, n); } const_iterator begin() const { return arrayref().begin(); } const_iterator end() const { return arrayref().begin() + m_count; } private: void destroy(iterator b, iterator e) { for (; b != e; ++b) b->~T(); } void shrink(iterator b) { destroy(b, end()); m_count = std::distance(begin(), b); } array m_bytes; array_type& arrayref() { return reinterpret_cast(m_bytes); } const array_type& arrayref() const { return reinterpret_cast(m_bytes); } };