// Copyright (c) 2015 Noah Lopez // Use, modification, and distribution is subject to the Boost Software // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef MSEMSEVECTOR_H #define MSEMSEVECTOR_H /*compiler specific defines*/ #ifdef _MSC_VER #if (1700 > _MSC_VER) #define MSVC2010_COMPATIBLE 1 #endif /*(1700 > _MSC_VER)*/ #if (1900 > _MSC_VER) #define MSVC2013_COMPATIBLE 1 #endif /*(1900 > _MSC_VER)*/ #else /*_MSC_VER*/ #if (defined(__GNUC__) || defined(__GNUG__)) #define GPP_COMPATIBLE 1 #if ((5 > __GNUC__) && (!defined(__clang__))) #define GPP4P8_COMPATIBLE 1 #endif /*((5 > __GNUC__) && (!defined(__clang__)))*/ #endif #endif /*_MSC_VER*/ //define MSE_MSEVECTOR_USE_MSE_PRIMITIVES 1 #ifdef MSE_MSEVECTOR_USE_MSE_PRIMITIVES #include "debug/mse/mseprimitives.h" #endif // MSE_MSEVECTOR_USE_MSE_PRIMITIVES #include #include #include #include #include #include // ULONG_MAX #include #ifdef MSE_CUSTOM_THROW_DEFINITION #include #define MSE_THROW(x) MSE_CUSTOM_THROW_DEFINITION(x) #else // MSE_CUSTOM_THROW_DEFINITION #define MSE_THROW(x) throw(x) #endif // MSE_CUSTOM_THROW_DEFINITION namespace mse { #ifdef MSE_MSEVECTOR_USE_MSE_PRIMITIVES typedef mse::CSize_t msev_size_t; typedef mse::CInt msev_int; typedef bool msev_bool; // no added safety benefit to using mse::CBool in this case #define msev_as_a_size_t as_a_size_t #else // MSE_MSEVECTOR_USE_MSE_PRIMITIVES #if SIZE_MAX <= ULONG_MAX #define MSE_MSEVECTOR_BASE_INTEGER_TYPE long int #else // SIZE_MAX <= ULONG_MAX #define MSE_MSEVECTOR_BASE_INTEGER_TYPE long long int #endif // SIZE_MAX <= ULONG_MAX typedef size_t msev_size_t; typedef MSE_MSEVECTOR_BASE_INTEGER_TYPE msev_int; typedef bool msev_bool; typedef size_t msev_as_a_size_t; #endif // MSE_MSEVECTOR_USE_MSE_PRIMITIVES class msevector_range_error : public std::range_error { public: using std::range_error::range_error; }; class msevector_null_dereference_error : public std::logic_error { public: using std::logic_error::logic_error; }; /* msev_pointer behaves similar to native pointers. It's a bit safer in that it initializes to nullptr by default and checks for attempted dereference of null pointers. */ template class msev_pointer { public: msev_pointer() : m_ptr(nullptr) {} msev_pointer(_Ty* ptr) : m_ptr(ptr) {} msev_pointer(const msev_pointer<_Ty>& src) : m_ptr(src.m_ptr) {} _Ty& operator*() const { #ifndef MSE_DISABLE_MSEAR_POINTER_CHECKS if (nullptr == m_ptr) { MSE_THROW(msevector_null_dereference_error("attempt to dereference null pointer - mse::msev_pointer")); } #endif /*MSE_DISABLE_MSEAR_POINTER_CHECKS*/ return (*m_ptr); } _Ty* operator->() const { #ifndef MSE_DISABLE_MSEAR_POINTER_CHECKS if (nullptr == m_ptr) { MSE_THROW(msevector_null_dereference_error("attempt to dereference null pointer - mse::msev_pointer")); } #endif /*MSE_DISABLE_MSEAR_POINTER_CHECKS*/ return m_ptr; } msev_pointer<_Ty>& operator=(_Ty* ptr) { m_ptr = ptr; return (*this); } bool operator==(const msev_pointer _Right_cref) const { return (_Right_cref.m_ptr == m_ptr); } bool operator!=(const msev_pointer _Right_cref) const { return (!((*this) == _Right_cref)); } bool operator==(const _Ty* _Right_cref) const { return (_Right_cref == m_ptr); } bool operator!=(const _Ty* _Right_cref) const { return (!((*this) == _Right_cref)); } bool operator!() const { return (!m_ptr); } operator bool() const { return (m_ptr != nullptr); } operator _Ty*() const { return m_ptr; } _Ty* m_ptr; }; #ifndef _XSTD #define _XSTD ::std:: #endif /*_XSTD*/ template struct integral_constant { // convenient template for integral constant types static const _Ty value = _Val; typedef _Ty value_type; typedef integral_constant<_Ty, _Val> type; operator value_type() const { // return stored value return (value); } }; template struct _mse_Is_iterator : public integral_constant::value> { // tests for reasonable iterator candidate }; template using _mse_RequireInputIter = typename std::enable_if< std::is_convertible::iterator_category, std::input_iterator_tag>::value //_mse_Is_iterator<_InIter>::value >::type; /* Note that, at the moment, msevector inherits publicly from std::vector. This is not intended to be a permanent characteristic of msevector and any reference to, or interpretation of, an msevector as an std::vector is (and has always been) depricated. msevector endeavors to support the subset of the std::vector interface that is compatible with the security/safety goals of msevector. (The remaining part of the std::vector interface may be supported, as a user option, for compatibility.) In particular, keep in mind that std::vector does not have a virtual destructor, so deallocating an msevector as an std::vector would result in memory leaks. */ template > class msevector : public std::vector<_Ty, _A> { public: typedef std::vector<_Ty, _A> base_class; typedef msevector<_Ty, _A> _Myt; typedef typename base_class::value_type value_type; //typedef typename base_class::size_type size_type; typedef msev_size_t size_type; //typedef typename base_class::difference_type difference_type; typedef msev_int difference_type; typedef typename base_class::pointer pointer; typedef typename base_class::const_pointer const_pointer; typedef typename base_class::reference reference; typedef typename base_class::const_reference const_reference; explicit msevector(const _A& _Al = _A()) : base_class(_Al), m_mmitset(*this) { /*m_debug_size = size();*/ } explicit msevector(size_type _N) : base_class(msev_as_a_size_t(_N)), m_mmitset(*this) { /*m_debug_size = size();*/ } explicit msevector(size_type _N, const _Ty& _V, const _A& _Al = _A()) : base_class(msev_as_a_size_t(_N), _V, _Al), m_mmitset(*this) { /*m_debug_size = size();*/ } msevector(base_class&& _X) : base_class(std::move(_X)), m_mmitset(*this) { /*m_debug_size = size();*/ } msevector(const base_class& _X) : base_class(_X), m_mmitset(*this) { /*m_debug_size = size();*/ } msevector(_Myt&& _X) : base_class(std::move(_X)), m_mmitset(*this) { /*m_debug_size = size();*/ } msevector(const _Myt& _X) : base_class(_X), m_mmitset(*this) { /*m_debug_size = size();*/ } typedef typename base_class::const_iterator _It; /* Note that safety cannot be guaranteed when using these constructors that take unsafe typename base_class::iterator and/or pointer parameters. */ msevector(_It _F, _It _L, const _A& _Al = _A()) : base_class(_F, _L, _Al), m_mmitset(*this) { /*m_debug_size = size();*/ } msevector(const _Ty* _F, const _Ty* _L, const _A& _Al = _A()) : base_class(_F, _L, _Al), m_mmitset(*this) { /*m_debug_size = size();*/ } template::value, void>::type , class = _mse_RequireInputIter<_Iter> > msevector(_Iter _First, _Iter _Last) : base_class(_First, _Last), m_mmitset(*this) { /*m_debug_size = size();*/ } template::value, void>::type , class = _mse_RequireInputIter<_Iter> > //msevector(_Iter _First, _Iter _Last, const typename base_class::_Alloc& _Al) : base_class(_First, _Last, _Al), m_mmitset(*this) { /*m_debug_size = size();*/ } msevector(_Iter _First, _Iter _Last, const _A& _Al) : base_class(_First, _Last, _Al), m_mmitset(*this) { /*m_debug_size = size();*/ } _Myt& operator=(const base_class& _X) { base_class::operator =(_X); /*m_debug_size = size();*/ m_mmitset.reset(); return (*this); } _Myt& operator=(_Myt&& _X) { operator=(std::move(static_cast(_X))); m_mmitset.reset(); return (*this); } _Myt& operator=(const _Myt& _X) { operator=(static_cast(_X)); m_mmitset.reset(); return (*this); } void reserve(size_type _Count) { // determine new minimum length of allocated storage auto original_capacity = msev_size_t((*this).capacity()); base_class::reserve(msev_as_a_size_t(_Count)); auto new_capacity = msev_size_t((*this).capacity()); bool realloc_occured = (new_capacity != original_capacity); if (realloc_occured) { m_mmitset.sync_iterators_to_index(); } } void shrink_to_fit() { // reduce capacity auto original_capacity = msev_size_t((*this).capacity()); base_class::shrink_to_fit(); auto new_capacity = msev_size_t((*this).capacity()); bool realloc_occured = (new_capacity != original_capacity); if (realloc_occured) { m_mmitset.sync_iterators_to_index(); } } void resize(size_type _N, const _Ty& _X = _Ty()) { auto original_size = msev_size_t((*this).size()); auto original_capacity = msev_size_t((*this).capacity()); bool shrinking = (_N < original_size); base_class::resize(msev_as_a_size_t(_N), _X); /*m_debug_size = size();*/ if (shrinking) { m_mmitset.invalidate_inclusive_range(_N, msev_size_t(original_size - 1)); } m_mmitset.shift_inclusive_range(original_size, original_size, msev_size_t(_N) - original_size); /*shift the end markers*/ auto new_capacity = msev_size_t((*this).capacity()); bool realloc_occured = (new_capacity != original_capacity); if (realloc_occured) { m_mmitset.sync_iterators_to_index(); } } typename base_class::const_reference operator[](size_type _P) const { return (*this).at(msev_as_a_size_t(_P)); } typename base_class::reference operator[](size_type _P) { return (*this).at(msev_as_a_size_t(_P)); } typename base_class::reference front() { // return first element of mutable sequence if (0 == (*this).size()) { MSE_THROW(msevector_range_error("front() on empty - typename base_class::reference front() - msevector")); } return base_class::front(); } typename base_class::const_reference front() const { // return first element of nonmutable sequence if (0 == (*this).size()) { MSE_THROW(msevector_range_error("front() on empty - typename base_class::const_reference front() - msevector")); } return base_class::front(); } typename base_class::reference back() { // return last element of mutable sequence if (0 == (*this).size()) { MSE_THROW(msevector_range_error("back() on empty - typename base_class::reference back() - msevector")); } return base_class::back(); } typename base_class::const_reference back() const { // return last element of nonmutable sequence if (0 == (*this).size()) { MSE_THROW(msevector_range_error("back() on empty - typename base_class::const_reference back() - msevector")); } return base_class::back(); } void push_back(_Ty&& _X) { if (m_mmitset.is_empty()) { base_class::push_back(std::move(_X)); } else { auto original_size = msev_size_t((*this).size()); auto original_capacity = msev_size_t((*this).capacity()); base_class::push_back(std::move(_X)); /*m_debug_size = size();*/ assert((original_size + 1) == msev_size_t((*this).size())); m_mmitset.shift_inclusive_range(original_size, original_size, 1); /*shift the end markers*/ auto new_capacity = msev_size_t((*this).capacity()); bool realloc_occured = (new_capacity != original_capacity); if (realloc_occured) { m_mmitset.sync_iterators_to_index(); } } } void push_back(const _Ty& _X) { if (m_mmitset.is_empty()) { base_class::push_back(_X); } else { auto original_size = msev_size_t((*this).size()); auto original_capacity = msev_size_t((*this).capacity()); base_class::push_back(_X); /*m_debug_size = size();*/ assert((original_size + 1) == msev_size_t((*this).size())); m_mmitset.shift_inclusive_range(original_size, original_size, 1); /*shift the end markers*/ auto new_capacity = msev_size_t((*this).capacity()); bool realloc_occured = (new_capacity != original_capacity); if (realloc_occured) { m_mmitset.sync_iterators_to_index(); } } } void pop_back() { if (m_mmitset.is_empty()) { base_class::pop_back(); } else { auto original_size = msev_size_t((*this).size()); auto original_capacity = msev_size_t((*this).capacity()); if (0 == original_size) { MSE_THROW(msevector_range_error("pop_back() on empty - void pop_back() - msevector")); } base_class::pop_back(); /*m_debug_size = size();*/ assert((original_size - 1) == msev_size_t((*this).size())); m_mmitset.invalidate_inclusive_range(msev_size_t(original_size - 1), msev_size_t(original_size - 1)); m_mmitset.shift_inclusive_range(original_size, original_size, -1); /*shift the end markers*/ auto new_capacity = msev_size_t((*this).capacity()); bool realloc_occured = (new_capacity != original_capacity); if (realloc_occured) { m_mmitset.sync_iterators_to_index(); } } } void assign(_It _F, _It _L) { base_class::assign(_F, _L); /*m_debug_size = size();*/ m_mmitset.reset(); } template void assign(_Iter _First, _Iter _Last) { // assign [_First, _Last) base_class::assign(_First, _Last); /*m_debug_size = size();*/ m_mmitset.reset(); } void assign(size_type _N, const _Ty& _X = _Ty()) { base_class::assign(msev_as_a_size_t(_N), _X); /*m_debug_size = size();*/ m_mmitset.reset(); } typename base_class::iterator insert(typename base_class::const_iterator _P, _Ty&& _X) { return (emplace(_P, std::move(_X))); } typename base_class::iterator insert(typename base_class::const_iterator _P, const _Ty& _X = _Ty()) { if (m_mmitset.is_empty()) { typename base_class::iterator retval = base_class::insert(_P, _X); /*m_debug_size = size();*/ return retval; } else { msev_int di = std::distance(base_class::cbegin(), _P); msev_size_t d = msev_size_t(di); if ((0 > di) || (msev_size_t((*this).size()) < di)) { MSE_THROW(msevector_range_error("index out of range - typename base_class::iterator insert() - msevector")); } auto original_size = msev_size_t((*this).size()); auto original_capacity = msev_size_t((*this).capacity()); typename base_class::iterator retval = base_class::insert(_P, _X); /*m_debug_size = size();*/ assert((original_size + 1) == msev_size_t((*this).size())); assert(di == std::distance(base_class::begin(), retval)); m_mmitset.shift_inclusive_range(d, original_size, 1); auto new_capacity = msev_size_t((*this).capacity()); bool realloc_occured = (new_capacity != original_capacity); if (realloc_occured) { m_mmitset.sync_iterators_to_index(); } return retval; } } #if !(defined(GPP4P8_COMPATIBLE)) typename base_class::iterator insert(typename base_class::const_iterator _P, size_type _M, const _Ty& _X) { if (m_mmitset.is_empty()) { typename base_class::iterator retval = base_class::insert(_P, msev_as_a_size_t(_M), _X); /*m_debug_size = size();*/ return retval; } else { msev_int di = std::distance(base_class::cbegin(), _P); msev_size_t d = msev_size_t(di); if ((0 > di) || ((*this).size() < msev_size_t(di))) { MSE_THROW(msevector_range_error("index out of range - typename base_class::iterator insert() - msevector")); } auto original_size = msev_size_t((*this).size()); auto original_capacity = msev_size_t((*this).capacity()); typename base_class::iterator retval = base_class::insert(_P, msev_as_a_size_t(_M), _X); /*m_debug_size = size();*/ assert((original_size + _M) == msev_size_t((*this).size())); assert(di == std::distance(base_class::begin(), retval)); m_mmitset.shift_inclusive_range(d, original_size, msev_int(_M)); auto new_capacity = msev_size_t((*this).capacity()); bool realloc_occured = (new_capacity != original_capacity); if (realloc_occured) { m_mmitset.sync_iterators_to_index(); } return retval; } } templatetypename std::enable_if<_mse_Is_iterator<_Iter>::value, typename base_class::iterator>::type , class = _mse_RequireInputIter<_Iter> > typename base_class::iterator insert(typename base_class::const_iterator _Where, _Iter _First, _Iter _Last) { // insert [_First, _Last) at _Where if (m_mmitset.is_empty()) { auto retval = base_class::insert(_Where, _First, _Last); /*m_debug_size = size();*/ return retval; } else { msev_int di = std::distance(base_class::cbegin(), _Where); msev_size_t d = msev_size_t(di); if ((0 > di) || ((*this).size() < msev_size_t(di))) { MSE_THROW(msevector_range_error("index out of range - typename base_class::iterator insert() - msevector")); } auto _M = msev_int(std::distance(_First, _Last)); auto original_size = msev_size_t((*this).size()); auto original_capacity = msev_size_t((*this).capacity()); //if (0 > _M) { MSE_THROW(msevector_range_error("invalid argument - typename base_class::iterator insert() - msevector")); } auto retval = base_class::insert(_Where, _First, _Last); /*m_debug_size = size();*/ assert((original_size + _M) == msev_size_t((*this).size())); assert(di == std::distance(base_class::begin(), retval)); m_mmitset.shift_inclusive_range(d, original_size, _M); auto new_capacity = msev_size_t((*this).capacity()); bool realloc_occured = (new_capacity != original_capacity); if (realloc_occured) { m_mmitset.sync_iterators_to_index(); } return retval; } } #else /*!(defined(GPP4P8_COMPATIBLE))*/ /*typename base_class::iterator*/ void /* g++4.8 seems to be using the c++98 version of this insert function instead of the c++11 version. */ insert(typename base_class::/*const_*/iterator _P, size_t _M, const _Ty& _X) { msev_int di = std::distance(base_class::/*c*/begin(), _P); msev_size_t d = msev_size_t(di); if ((0 > di) || (msev_size_t((*this).size()) < di)) { MSE_THROW(msevector_range_error("index out of range - typename base_class::iterator insert() - msevector")); } auto original_size = msev_size_t((*this).size()); auto original_capacity = msev_size_t((*this).capacity()); /*typename base_class::iterator retval =*/ base_class::insert(_P, _M, _X); /*m_debug_size = size();*/ assert((original_size + _M) == msev_size_t((*this).size())); /*assert(di == std::distance(base_class::begin(), retval));*/ m_mmitset.shift_inclusive_range(d, original_size, _M); auto new_capacity = msev_size_t((*this).capacity()); bool realloc_occured = (new_capacity != original_capacity); if (realloc_occured) { m_mmitset.sync_iterators_to_index(); } /*return retval;*/ } templatetypename std::enable_if<_mse_Is_iterator<_Iter>::value, void>::type , class = _mse_RequireInputIter<_Iter> > void insert(typename base_class::/*const_*/iterator _Where, _Iter _First, _Iter _Last) { // insert [_First, _Last) at _Where msev_int di = std::distance(base_class::/*c*/begin(), _Where); msev_size_t d = msev_size_t(di); if ((0 > di) || (msev_size_t((*this).size()) < di)) { MSE_THROW(msevector_range_error("index out of range - typename base_class::iterator insert() - msevector")); } auto _M = msev_int(std::distance(_First, _Last)); auto original_size = msev_size_t((*this).size()); auto original_capacity = msev_size_t((*this).capacity()); //if (0 > _M) { MSE_THROW(msevector_range_error("invalid argument - typename base_class::iterator insert() - msevector")); } /*auto retval =*/ base_class::insert(_Where, _First, _Last); /*m_debug_size = size();*/ assert((original_size + _M) == msev_size_t((*this).size())); /*assert(di == std::distance(base_class::begin(), retval));*/ m_mmitset.shift_inclusive_range(d, original_size, _M); auto new_capacity = msev_size_t((*this).capacity()); bool realloc_occured = (new_capacity != original_capacity); if (realloc_occured) { m_mmitset.sync_iterators_to_index(); } /*return retval;*/ } #endif /*!(defined(GPP4P8_COMPATIBLE))*/ template void emplace_back(_Valty&& ..._Val) { // insert by moving into element at end if (m_mmitset.is_empty()) { base_class::emplace_back(std::forward<_Valty>(_Val)...); /*m_debug_size = size();*/ } else { auto original_size = msev_size_t((*this).size()); auto original_capacity = msev_size_t((*this).capacity()); base_class::emplace_back(std::forward<_Valty>(_Val)...); /*m_debug_size = size();*/ assert((original_size + 1) == msev_size_t((*this).size())); m_mmitset.shift_inclusive_range(original_size, original_size, 1); /*shift the end markers*/ auto new_capacity = msev_size_t((*this).capacity()); bool realloc_occured = (new_capacity != original_capacity); if (realloc_occured) { m_mmitset.sync_iterators_to_index(); } } } template #if !(defined(GPP4P8_COMPATIBLE)) typename base_class::iterator emplace(typename base_class::const_iterator _Where, _Valty&& ..._Val) { // insert by moving _Val at _Where #else /*!(defined(GPP4P8_COMPATIBLE))*/ typename base_class::iterator emplace(typename base_class::/*const_*/iterator _Where, _Valty&& ..._Val) { // insert by moving _Val at _Where #endif /*!(defined(GPP4P8_COMPATIBLE))*/ if (m_mmitset.is_empty()) { auto retval = base_class::emplace(_Where, std::forward<_Valty>(_Val)...); /*m_debug_size = size();*/ return retval; } else { #if !(defined(GPP4P8_COMPATIBLE)) msev_int di = std::distance(base_class::cbegin(), _Where); #else /*!(defined(GPP4P8_COMPATIBLE))*/ msev_int di = std::distance(base_class::/*c*/begin(), _Where); #endif /*!(defined(GPP4P8_COMPATIBLE))*/ msev_size_t d = msev_size_t(di); if ((0 > di) || ((*this).size() < msev_size_t(di))) { MSE_THROW(msevector_range_error("index out of range - typename base_class::iterator emplace() - msevector")); } auto original_size = msev_size_t((*this).size()); auto original_capacity = msev_size_t((*this).capacity()); auto retval = base_class::emplace(_Where, std::forward<_Valty>(_Val)...); /*m_debug_size = size();*/ assert((original_size + 1) == msev_size_t((*this).size())); assert(di == std::distance(base_class::begin(), retval)); m_mmitset.shift_inclusive_range(d, original_size, 1); auto new_capacity = msev_size_t((*this).capacity()); bool realloc_occured = (new_capacity != original_capacity); if (realloc_occured) { m_mmitset.sync_iterators_to_index(); } return retval; } } typename base_class::iterator erase(typename base_class::const_iterator _P) { if (m_mmitset.is_empty()) { typename base_class::iterator retval = base_class::erase(_P); /*m_debug_size = size();*/ return retval; } else { msev_int di = std::distance(base_class::cbegin(), _P); msev_size_t d = msev_size_t(di); if ((0 > di) || ((*this).size() < msev_size_t(di))) { MSE_THROW(msevector_range_error("index out of range - typename base_class::iterator erase() - msevector")); } auto original_size = msev_size_t((*this).size()); auto original_capacity = msev_size_t((*this).capacity()); if (base_class::end() == _P) { MSE_THROW(msevector_range_error("invalid argument - typename base_class::iterator erase(typename base_class::const_iterator _P) - msevector")); } typename base_class::iterator retval = base_class::erase(_P); /*m_debug_size = size();*/ assert((original_size - 1) == msev_size_t((*this).size())); assert(di == std::distance(base_class::begin(), retval)); { m_mmitset.invalidate_inclusive_range(d, d); m_mmitset.shift_inclusive_range(msev_size_t(d + 1), original_size, -1); } auto new_capacity = msev_size_t((*this).capacity()); bool realloc_occured = (new_capacity != original_capacity); if (realloc_occured) { m_mmitset.sync_iterators_to_index(); } return retval; } } typename base_class::iterator erase(typename base_class::const_iterator _F, typename base_class::const_iterator _L) { if (m_mmitset.is_empty()) { typename base_class::iterator retval = base_class::erase(_F, _L); /*m_debug_size = size();*/ return retval; } else { msev_int di = std::distance(base_class::cbegin(), _F); msev_size_t d = msev_size_t(di); if ((0 > di) || ((*this).size() < msev_size_t(di))) { MSE_THROW(msevector_range_error("index out of range - typename base_class::iterator erase() - msevector")); } msev_int di2 = std::distance(base_class::cbegin(), _L); msev_size_t d2 = msev_size_t(di2); if ((0 > di2) || ((*this).size() < msev_size_t(di2))) { MSE_THROW(msevector_range_error("index out of range - typename base_class::iterator erase() - msevector")); } auto _M = msev_int(std::distance(_F, _L)); auto original_size = msev_size_t((*this).size()); auto original_capacity = msev_size_t((*this).capacity()); if ((base_class::end() == _F)/* || (0 > _M)*/) { MSE_THROW(msevector_range_error("invalid argument - typename base_class::iterator erase(typename base_class::iterator _F, typename base_class::iterator _L) - msevector")); } typename base_class::iterator retval = base_class::erase(_F, _L); /*m_debug_size = size();*/ assert((original_size - _M) == msev_size_t((*this).size())); assert(di == std::distance(base_class::begin(), retval)); { if (1 <= _M) { m_mmitset.invalidate_inclusive_range(d, msev_size_t(d + _M - 1)); } m_mmitset.shift_inclusive_range(msev_size_t(d + _M), original_size, -_M); } auto new_capacity = msev_size_t((*this).capacity()); bool realloc_occured = (new_capacity != original_capacity); if (realloc_occured) { m_mmitset.sync_iterators_to_index(); } return retval; } } void clear() { base_class::clear(); /*m_debug_size = size();*/ m_mmitset.reset(); } void swap(base_class& _X) { base_class::swap(_X); /*m_debug_size = size();*/ m_mmitset.reset(); } void swap(_Myt& _X) { swap(static_cast(_X)); m_mmitset.reset(); } msevector(_XSTD initializer_list _Ilist, const _A& _Al = _A()) : base_class(_Ilist, _Al), m_mmitset(*this) { // construct from initializer_list /*m_debug_size = size();*/ } _Myt& operator=(_XSTD initializer_list _Ilist) { // assign initializer_list operator=(static_cast(_Ilist)); m_mmitset.reset(); return (*this); } void assign(_XSTD initializer_list _Ilist) { // assign initializer_list base_class::assign(_Ilist); /*m_debug_size = size();*/ m_mmitset.reset(); } #if defined(GPP4P8_COMPATIBLE) /* g++4.8 seems to be (incorrectly) using the c++98 version of this insert function instead of the c++11 version. */ /*typename base_class::iterator*/void insert(typename base_class::/*const_*/iterator _Where, _XSTD initializer_list _Ilist) { // insert initializer_list msev_int di = std::distance(base_class::/*c*/begin(), _Where); msev_size_t d = msev_size_t(di); if ((0 > di) || (msev_size_t((*this).size()) < di)) { MSE_THROW(msevector_range_error("index out of range - typename base_class::iterator insert() - msevector")); } auto _M = _Ilist.size(); auto original_size = msev_size_t((*this).size()); auto original_capacity = msev_size_t((*this).capacity()); /*auto retval = */base_class::insert(_Where, _Ilist); /*m_debug_size = size();*/ assert((original_size + _M) == msev_size_t((*this).size())); /*assert(di == std::distance(base_class::begin(), retval));*/ m_mmitset.shift_inclusive_range(d, original_size, _M); auto new_capacity = msev_size_t((*this).capacity()); bool realloc_occured = (new_capacity != original_capacity); if (realloc_occured) { m_mmitset.sync_iterators_to_index(); } /*return retval;*/ } #else /*defined(GPP4P8_COMPATIBLE)*/ typename base_class::iterator insert(typename base_class::const_iterator _Where, _XSTD initializer_list _Ilist) { // insert initializer_list if (m_mmitset.is_empty()) { auto retval = base_class::insert(_Where, _Ilist); /*m_debug_size = size();*/ return retval; } else { msev_int di = std::distance(base_class::cbegin(), _Where); msev_size_t d = msev_size_t(di); if ((0 > di) || ((*this).size() < msev_size_t(di))) { MSE_THROW(msevector_range_error("index out of range - typename base_class::iterator insert() - msevector")); } auto _M = _Ilist.size(); auto original_size = msev_size_t((*this).size()); auto original_capacity = msev_size_t((*this).capacity()); auto retval = base_class::insert(_Where, _Ilist); /*m_debug_size = size();*/ assert((original_size + _M) == msev_size_t((*this).size())); assert(di == std::distance(base_class::begin(), retval)); m_mmitset.shift_inclusive_range(d, original_size, msev_int(_M)); auto new_capacity = msev_size_t((*this).capacity()); bool realloc_occured = (new_capacity != original_capacity); if (realloc_occured) { m_mmitset.sync_iterators_to_index(); } return retval; } } #endif /*defined(GPP4P8_COMPATIBLE)*/ //size_t m_debug_size; class random_access_const_iterator_base : public std::iterator {}; class random_access_iterator_base : public std::iterator {}; /* mm_const_iterator_type acts much like a list iterator. */ class mm_const_iterator_type : public random_access_const_iterator_base { public: typedef typename base_class::const_iterator::iterator_category iterator_category; typedef typename base_class::const_iterator::value_type value_type; //typedef typename base_class::const_iterator::difference_type difference_type; typedef msev_int difference_type; typedef difference_type distance_type; // retained typedef typename base_class::const_iterator::pointer pointer; typedef typename base_class::const_iterator::pointer const_pointer; typedef typename base_class::const_iterator::reference reference; typedef typename base_class::const_reference const_reference; void reset() { set_to_end_marker(); } bool points_to_an_item() const { if (m_points_to_an_item) { assert((1 <= m_owner_cptr->size()) && (m_index < m_owner_cptr->size())); return true; } else { assert(!((1 <= m_owner_cptr->size()) && (m_index < m_owner_cptr->size()))); return false; } } bool points_to_end_marker() const { if (false == points_to_an_item()) { assert(m_index == m_owner_cptr->size()); return true; } else { return false; } } bool points_to_beginning() const { if (0 == m_index) { return true; } else { return false; } } /* has_next_item_or_end_marker() is just an alias for points_to_an_item(). */ bool has_next_item_or_end_marker() const { return points_to_an_item(); } //his is /* has_next() is just an alias for points_to_an_item() that's familiar to java programmers. */ bool has_next() const { return has_next_item_or_end_marker(); } bool has_previous() const { return (!points_to_beginning()); } void set_to_beginning() { m_index = 0; if (1 <= m_owner_cptr->size()) { m_points_to_an_item = true; } else { assert(false == m_points_to_an_item); } } void set_to_end_marker() { m_index = m_owner_cptr->size(); m_points_to_an_item = false; } void set_to_next() { if (points_to_an_item()) { m_index += 1; if (m_owner_cptr->size() <= m_index) { (*this).m_points_to_an_item = false; if (m_owner_cptr->size() < m_index) { assert(false); reset(); } } } else { MSE_THROW(msevector_range_error("attempt to use invalid const_item_pointer - void set_to_next() - mm_const_iterator_type - msevector")); } } void set_to_previous() { if (has_previous()) { m_index -= 1; (*this).m_points_to_an_item = true; } else { MSE_THROW(msevector_range_error("attempt to use invalid const_item_pointer - void set_to_previous() - mm_const_iterator_type - msevector")); } } mm_const_iterator_type& operator ++() { (*this).set_to_next(); return (*this); } mm_const_iterator_type operator++(int) { mm_const_iterator_type _Tmp = *this; ++*this; return (_Tmp); } mm_const_iterator_type& operator --() { (*this).set_to_previous(); return (*this); } mm_const_iterator_type operator--(int) { mm_const_iterator_type _Tmp = *this; --*this; return (_Tmp); } void advance(difference_type n) { auto new_index = msev_int(m_index) + n; if ((0 > new_index) || (m_owner_cptr->size() < msev_size_t(new_index))) { MSE_THROW(msevector_range_error("index out of range - void advance(difference_type n) - mm_const_iterator_type - msevector")); } else { m_index = msev_size_t(new_index); if (m_owner_cptr->size() <= m_index) { (*this).m_points_to_an_item = false; } else { (*this).m_points_to_an_item = true; } } } void regress(difference_type n) { advance(-n); } mm_const_iterator_type& operator +=(difference_type n) { (*this).advance(n); return (*this); } mm_const_iterator_type& operator -=(difference_type n) { (*this).regress(n); return (*this); } mm_const_iterator_type operator+(difference_type n) const { mm_const_iterator_type retval(*this); retval = (*this); retval.advance(n); return retval; } mm_const_iterator_type operator-(difference_type n) const { return ((*this) + (-n)); } difference_type operator-(const mm_const_iterator_type &rhs) const { if ((rhs.m_owner_cptr) != ((*this).m_owner_cptr)) { MSE_THROW(msevector_range_error("invalid argument - difference_type operator-(const mm_const_iterator_type &rhs) const - msevector::mm_const_iterator_type")); } auto retval = difference_type((*this).m_index) - difference_type(rhs.m_index); assert(difference_type(m_owner_cptr->size()) >= retval); return retval; } const_reference operator*() const { return m_owner_cptr->at(msev_as_a_size_t(m_index)); } const_reference item() const { return operator*(); } const_reference previous_item() const { return m_owner_cptr->at(msev_as_a_size_t(m_index - 1)); } const_pointer operator->() const { return &(m_owner_cptr->at(msev_as_a_size_t(m_index))); } const_reference operator[](difference_type _Off) const { return (*m_owner_cptr).at(msev_as_a_size_t(difference_type(m_index) + _Off)); } /* mm_const_iterator_type& operator=(const typename base_class::const_iterator& _Right_cref) { msev_int d = std::distance(m_owner_cptr->cbegin(), _Right_cref); if ((0 <= d) && (m_owner_cptr->size() >= d)) { if (m_owner_cptr->size() == d) { assert(m_owner_cptr->cend() == _Right_cref); m_points_to_an_item = false; } else { m_points_to_an_item = true; } m_index = msev_size_t(d); base_class::const_iterator::operator=(_Right_cref); } else { MSE_THROW(msevector_range_error("doesn't seem to be a valid assignment value - mm_const_iterator_type& operator=(const typename base_class::const_iterator& _Right_cref) - mm_const_iterator_type - msevector")); } return (*this); } */ mm_const_iterator_type& operator=(const mm_const_iterator_type& _Right_cref) { if (((*this).m_owner_cptr) == (_Right_cref.m_owner_cptr)) { assert((*this).m_owner_cptr->size() >= _Right_cref.m_index); (*this).m_points_to_an_item = _Right_cref.m_points_to_an_item; (*this).m_index = _Right_cref.m_index; } else { MSE_THROW(msevector_range_error("doesn't seem to be a valid assignment value - mm_const_iterator_type& operator=(const typename base_class::iterator& _Right_cref) - mm_const_iterator_type - msevector")); } return (*this); } bool operator==(const mm_const_iterator_type& _Right_cref) const { if (((*this).m_owner_cptr) != (_Right_cref.m_owner_cptr)) { MSE_THROW(msevector_range_error("invalid argument - mm_const_iterator_type& operator==(const mm_const_iterator_type& _Right) - mm_const_iterator_type - msevector")); } return (_Right_cref.m_index == m_index); } bool operator!=(const mm_const_iterator_type& _Right_cref) const { return (!(_Right_cref == (*this))); } bool operator<(const mm_const_iterator_type& _Right) const { if (((*this).m_owner_cptr) != (_Right.m_owner_cptr)) { MSE_THROW(msevector_range_error("invalid argument - mm_const_iterator_type& operator<(const mm_const_iterator_type& _Right) - mm_const_iterator_type - msevector")); } return (m_index < _Right.m_index); } bool operator<=(const mm_const_iterator_type& _Right) const { return (((*this) < _Right) || (_Right == (*this))); } bool operator>(const mm_const_iterator_type& _Right) const { return (!((*this) <= _Right)); } bool operator>=(const mm_const_iterator_type& _Right) const { return (!((*this) < _Right)); } void set_to_const_item_pointer(const mm_const_iterator_type& _Right_cref) { (*this) = _Right_cref; } void invalidate_inclusive_range(msev_size_t index_of_first, msev_size_t index_of_last) { if ((index_of_first <= (*this).m_index) && (index_of_last >= (*this).m_index)) { (*this).reset(); } } void shift_inclusive_range(msev_size_t index_of_first, msev_size_t index_of_last, msev_int shift) { if ((index_of_first <= (*this).m_index) && (index_of_last >= (*this).m_index)) { auto new_index = (*this).m_index + shift; if ((0 > new_index) || (m_owner_cptr->size() < new_index)) { MSE_THROW(msevector_range_error("void shift_inclusive_range() - mm_const_iterator_type - msevector")); } else { (*this).m_index = msev_size_t(new_index); (*this).sync_const_iterator_to_index(); } } } msev_size_t position() const { return m_index; } operator typename base_class::const_iterator() const { typename base_class::const_iterator retval = (*m_owner_cptr).cbegin(); retval += msev_as_a_size_t(m_index); return retval; } /* We actually want to make this constructor private, but doing so seems to break std::make_shared. */ mm_const_iterator_type(const _Myt& owner_cref) : m_owner_cptr(&owner_cref) { set_to_beginning(); } private: mm_const_iterator_type(const mm_const_iterator_type& src_cref) : m_owner_cptr(src_cref.m_owner_cptr) { (*this) = src_cref; } void sync_const_iterator_to_index() { assert(m_owner_cptr->size() >= (*this).m_index); } msev_bool m_points_to_an_item = false; msev_size_t m_index = 0; const _Myt* m_owner_cptr = nullptr; friend class mm_iterator_set_type; friend class /*_Myt*/msevector<_Ty, _A>; friend class mm_iterator_type; }; /* mm_iterator_type acts much like a list iterator. */ class mm_iterator_type : random_access_iterator_base { public: typedef typename base_class::iterator::iterator_category iterator_category; typedef typename base_class::iterator::value_type value_type; //typedef typename base_class::iterator::difference_type difference_type; typedef msev_int difference_type; typedef difference_type distance_type; // retained typedef typename base_class::iterator::pointer pointer; typedef typename base_class::iterator::reference reference; void reset() { set_to_end_marker(); } bool points_to_an_item() const { if (m_points_to_an_item) { assert((1 <= m_owner_ptr->size()) && (m_index < m_owner_ptr->size())); return true; } else { assert(!((1 <= m_owner_ptr->size()) && (m_index < m_owner_ptr->size()))); return false; } } bool points_to_end_marker() const { if (false == points_to_an_item()) { assert(m_index == m_owner_ptr->size()); return true; } else { return false; } } bool points_to_beginning() const { if (0 == m_index) { return true; } else { return false; } } /* has_next_item_or_end_marker() is just an alias for points_to_an_item(). */ bool has_next_item_or_end_marker() const { return points_to_an_item(); } /* has_next() is just an alias for points_to_an_item() that's familiar to java programmers. */ bool has_next() const { return has_next_item_or_end_marker(); } bool has_previous() const { return (!points_to_beginning()); } void set_to_beginning() { m_index = 0; if (1 <= m_owner_ptr->size()) { m_points_to_an_item = true; } else { assert(false == m_points_to_an_item); } } void set_to_end_marker() { m_index = m_owner_ptr->size(); m_points_to_an_item = false; } void set_to_next() { if (points_to_an_item()) { m_index += 1; if (m_owner_ptr->size() <= m_index) { (*this).m_points_to_an_item = false; if (m_owner_ptr->size() < m_index) { assert(false); reset(); } } } else { MSE_THROW(msevector_range_error("attempt to use invalid item_pointer - void set_to_next() - mm_const_iterator_type - msevector")); } } void set_to_previous() { if (has_previous()) { m_index -= 1; (*this).m_points_to_an_item = true; } else { MSE_THROW(msevector_range_error("attempt to use invalid item_pointer - void set_to_previous() - mm_iterator_type - msevector")); } } mm_iterator_type& operator ++() { (*this).set_to_next(); return (*this); } mm_iterator_type operator++(int) { mm_iterator_type _Tmp = *this; ++*this; return (_Tmp); } mm_iterator_type& operator --() { (*this).set_to_previous(); return (*this); } mm_iterator_type operator--(int) { mm_iterator_type _Tmp = *this; --*this; return (_Tmp); } void advance(difference_type n) { auto new_index = msev_int(m_index) + n; if ((0 > new_index) || (m_owner_ptr->size() < msev_size_t(new_index))) { MSE_THROW(msevector_range_error("index out of range - void advance(difference_type n) - mm_iterator_type - msevector")); } else { m_index = msev_size_t(new_index); if (m_owner_ptr->size() <= m_index) { (*this).m_points_to_an_item = false; } else { (*this).m_points_to_an_item = true; } } } void regress(int n) { advance(-n); } mm_iterator_type& operator +=(difference_type n) { (*this).advance(n); return (*this); } mm_iterator_type& operator -=(difference_type n) { (*this).regress(n); return (*this); } mm_iterator_type operator+(difference_type n) const { mm_iterator_type retval(*this); retval = (*this); retval.advance(n); return retval; } mm_iterator_type operator-(difference_type n) const { return ((*this) + (-n)); } difference_type operator-(const mm_iterator_type& rhs) const { if ((rhs.m_owner_ptr) != ((*this).m_owner_ptr)) { MSE_THROW(msevector_range_error("invalid argument - difference_type operator-(const mm_iterator_type& rhs) const - msevector::mm_iterator_type")); } auto retval = difference_type((*this).m_index) - difference_type(rhs.m_index); assert(difference_type(m_owner_ptr->size()) >= retval); return retval; } reference operator*() const { return m_owner_ptr->at(msev_as_a_size_t(m_index)); } reference item() const { return operator*(); } reference previous_item() const { return m_owner_ptr->at(msev_as_a_size_t(m_index - 1)); } pointer operator->() const { return &(m_owner_ptr->at(msev_as_a_size_t(m_index))); } reference operator[](difference_type _Off) const { return (*m_owner_ptr).at(msev_as_a_size_t(difference_type(m_index) + _Off)); } /* mm_iterator_type& operator=(const typename base_class::iterator& _Right_cref) { msev_int d = std::distance(m_owner_ptr->begin(), _Right_cref); if ((0 <= d) && (m_owner_ptr->size() >= d)) { if (m_owner_ptr->size() == d) { assert(m_owner_ptr->end() == _Right_cref); m_points_to_an_item = false; } else { m_points_to_an_item = true; } m_index = msev_size_t(d); base_class::iterator::operator=(_Right_cref); } else { MSE_THROW(msevector_range_error("doesn't seem to be a valid assignment value - mm_iterator_type& operator=(const typename base_class::iterator& _Right_cref) - mm_const_iterator_type - msevector")); } return (*this); } */ mm_iterator_type& operator=(const mm_iterator_type& _Right_cref) { if (((*this).m_owner_ptr) == (_Right_cref.m_owner_ptr)) { assert((*this).m_owner_ptr->size() >= _Right_cref.m_index); (*this).m_points_to_an_item = _Right_cref.m_points_to_an_item; (*this).m_index = _Right_cref.m_index; } else { MSE_THROW(msevector_range_error("doesn't seem to be a valid assignment value - mm_iterator_type& operator=(const typename base_class::iterator& _Right_cref) - mm_const_iterator_type - msevector")); } return (*this); } bool operator==(const mm_iterator_type& _Right_cref) const { if (((*this).m_owner_ptr) != (_Right_cref.m_owner_ptr)) { MSE_THROW(msevector_range_error("invalid argument - mm_iterator_type& operator==(const typename base_class::iterator& _Right) - mm_iterator_type - msevector")); } return (_Right_cref.m_index == m_index); } bool operator!=(const mm_iterator_type& _Right_cref) const { return (!(_Right_cref == (*this))); } bool operator<(const mm_iterator_type& _Right) const { if (((*this).m_owner_ptr) != (_Right.m_owner_ptr)) { MSE_THROW(msevector_range_error("invalid argument - mm_iterator_type& operator<(const typename base_class::iterator& _Right) - mm_iterator_type - msevector")); } return (m_index < _Right.m_index); } bool operator<=(const mm_iterator_type& _Right) const { return (((*this) < _Right) || (_Right == (*this))); } bool operator>(const mm_iterator_type& _Right) const { return (!((*this) <= _Right)); } bool operator>=(const mm_iterator_type& _Right) const { return (!((*this) < _Right)); } void set_to_item_pointer(const mm_iterator_type& _Right_cref) { (*this) = _Right_cref; } void invalidate_inclusive_range(msev_size_t index_of_first, msev_size_t index_of_last) { if ((index_of_first <= (*this).m_index) && (index_of_last >= (*this).m_index)) { (*this).reset(); } } void shift_inclusive_range(msev_size_t index_of_first, msev_size_t index_of_last, msev_int shift) { if ((index_of_first <= (*this).m_index) && (index_of_last >= (*this).m_index)) { auto new_index = (*this).m_index + shift; if ((0 > new_index) || (m_owner_ptr->size() < new_index)) { MSE_THROW(msevector_range_error("void shift_inclusive_range() - mm_iterator_type - msevector")); } else { (*this).m_index = msev_size_t(new_index); (*this).sync_iterator_to_index(); } } } msev_size_t position() const { return m_index; } operator mm_const_iterator_type() const { mm_const_iterator_type retval(*m_owner_ptr); retval.set_to_beginning(); retval.advance(msev_int(m_index)); return retval; } /* We actually want to make this constructor private, but doing so seems to break std::make_shared. */ mm_iterator_type(_Myt& owner_ref) : m_owner_ptr(&owner_ref) { set_to_beginning(); } private: mm_iterator_type(const mm_iterator_type& src_cref) : m_owner_ptr(src_cref.m_owner_ptr) { (*this) = src_cref; } void sync_iterator_to_index() { assert(m_owner_ptr->size() >= (*this).m_index); } msev_bool m_points_to_an_item = false; msev_size_t m_index = 0; _Myt* m_owner_ptr = nullptr; friend class mm_iterator_set_type; friend class /*_Myt*/msevector<_Ty, _A>; }; private: typedef std::size_t CHashKey1; class mm_const_iterator_handle_type { public: mm_const_iterator_handle_type(const CHashKey1& key_cref, const std::shared_ptr& shptr_cref) : m_shptr(shptr_cref), m_key(key_cref) {} private: std::shared_ptr m_shptr; CHashKey1 m_key; friend class /*_Myt*/msevector<_Ty, _A>; friend class mm_iterator_set_type; }; class mm_iterator_handle_type { public: mm_iterator_handle_type(const CHashKey1& key_cref, const std::shared_ptr& shptr_ref) : m_shptr(shptr_ref), m_key(key_cref) {} private: std::shared_ptr m_shptr; CHashKey1 m_key; friend class /*_Myt*/msevector<_Ty, _A>; friend class mm_iterator_set_type; }; class mm_iterator_set_type { public: class CMMConstIterators : public std::unordered_map> {}; class CMMIterators : public std::unordered_map> {}; class assignable_CMMConstIterators_value_type : public std::pair> { public: assignable_CMMConstIterators_value_type() {} assignable_CMMConstIterators_value_type(const typename CMMConstIterators::value_type& src) : std::pair>(src.first, src.second) {} assignable_CMMConstIterators_value_type& operator=(const typename CMMConstIterators::value_type& rhs) { (*this).first = rhs.first; (*this).second = rhs.second; return (*this); } operator typename CMMConstIterators::value_type() const { return CMMConstIterators::value_type((*this).first, (*this).second); } }; class assignable_CMMIterators_value_type : public std::pair> { public: assignable_CMMIterators_value_type() {} assignable_CMMIterators_value_type(const typename CMMIterators::value_type& src) : std::pair>(src.first, src.second) {} assignable_CMMIterators_value_type& operator=(const typename CMMIterators::value_type& rhs) { (*this).first = rhs.first; (*this).second = rhs.second; return (*this); } operator typename CMMIterators::value_type() const { return CMMIterators::value_type((*this).first, (*this).second); } }; ~mm_iterator_set_type() { if (!mm_const_fast_mode1()) { delete m_aux_mm_const_iterator_shptrs_ptr; } if (!mm_fast_mode1()) { delete m_aux_mm_iterator_shptrs_ptr; } } void apply_to_all_mm_const_iterator_shptrs(const std::function&)>& func_obj_ref) { if (!mm_const_fast_mode1()) { for (auto it = (*m_aux_mm_const_iterator_shptrs_ptr).begin(); (*m_aux_mm_const_iterator_shptrs_ptr).end() != it; it++) { func_obj_ref((*it).second); } } else { for (int i = 0; i < m_fm1_num_mm_const_iterators; i += 1) { func_obj_ref(m_fm1_key_mm_const_it_array[i].second); } } } void apply_to_all_mm_iterator_shptrs(const std::function&)>& func_obj_ref) { if (!mm_fast_mode1()) { for (auto it = (*m_aux_mm_iterator_shptrs_ptr).begin(); (*m_aux_mm_iterator_shptrs_ptr).end() != it; it++) { func_obj_ref((*it).second); } } else { for (int i = 0; i < m_fm1_num_mm_iterators; i += 1) { func_obj_ref(m_fm1_key_mm_it_array[i].second); } } } mm_iterator_set_type(_Myt& owner_ref) : m_next_available_key(0), m_owner_ptr(&owner_ref) {} void reset() { /* We can use "static" here because the lambda function does not capture any parameters. */ static const std::function&)> cit_func_obj = [](std::shared_ptr& a) { a->reset(); }; apply_to_all_mm_const_iterator_shptrs(cit_func_obj); static const std::function&)> it_func_obj = [](std::shared_ptr& a) { a->reset(); }; apply_to_all_mm_iterator_shptrs(it_func_obj); } void sync_iterators_to_index() { /* No longer used. Relic from when mm_iterator_type contained a "native" iterator. */ /* We can use "static" here because the lambda function does not capture any parameters. */ /* static const std::function&)> cit_func_obj = [](std::shared_ptr& a) { a->sync_const_iterator_to_index(); }; apply_to_all_mm_const_iterator_shptrs(cit_func_obj); static const std::function&)> it_func_obj = [](std::shared_ptr& a) { a->sync_iterator_to_index(); }; apply_to_all_mm_iterator_shptrs(it_func_obj); */ } void invalidate_inclusive_range(msev_size_t start_index, msev_size_t end_index) { const std::function&)> cit_func_obj = [start_index, end_index](std::shared_ptr& a) { a->invalidate_inclusive_range(start_index, end_index); }; apply_to_all_mm_const_iterator_shptrs(cit_func_obj); const std::function&)> it_func_obj = [start_index, end_index](std::shared_ptr& a) { a->invalidate_inclusive_range(start_index, end_index); }; apply_to_all_mm_iterator_shptrs(it_func_obj); } void shift_inclusive_range(msev_size_t start_index, msev_size_t end_index, msev_int shift) { const std::function&)> cit_func_obj = [start_index, end_index, shift](std::shared_ptr& a) { a->shift_inclusive_range(start_index, end_index, shift); }; apply_to_all_mm_const_iterator_shptrs(cit_func_obj); const std::function&)> it_func_obj = [start_index, end_index, shift](std::shared_ptr& a) { a->shift_inclusive_range(start_index, end_index, shift); }; apply_to_all_mm_iterator_shptrs(it_func_obj); } bool is_empty() const { if (mm_const_fast_mode1()) { if (1 <= m_fm1_num_mm_const_iterators) { return false; } } else { if (1 <= m_aux_mm_const_iterator_shptrs_ptr->size()) { return false; } } if (mm_fast_mode1()) { if (1 <= m_fm1_num_mm_iterators) { return false; } } else { if (1 <= m_aux_mm_iterator_shptrs_ptr->size()) { return false; } } return true; } mm_const_iterator_handle_type allocate_new_const_item_pointer() { //auto shptr = std::shared_ptr(new mm_const_iterator_type(*m_owner_ptr)); auto shptr = std::make_shared(*m_owner_ptr); auto key = m_next_available_key; m_next_available_key++; mm_const_iterator_handle_type retval(key, shptr); typename CMMConstIterators::value_type new_item(key, shptr); if (!mm_const_fast_mode1()) { (*m_aux_mm_const_iterator_shptrs_ptr).insert(new_item); } else { if (sc_fm1_max_mm_iterators == m_fm1_num_mm_const_iterators) { /* Too many items. Initiate and switch to slow mode. */ /* Initialize slow storage. */ m_aux_mm_const_iterator_shptrs_ptr = new CMMConstIterators(); /* First copy the items from fast storage to slow storage. */ for (int i = 0; i < sc_fm1_max_mm_iterators; i += 1) { (*m_aux_mm_const_iterator_shptrs_ptr).insert(m_fm1_key_mm_const_it_array[i]); } /* Add the new items to slow storage. */ (*m_aux_mm_const_iterator_shptrs_ptr).insert(new_item); } else { m_fm1_key_mm_const_it_array[m_fm1_num_mm_const_iterators] = new_item; m_fm1_num_mm_const_iterators += 1; } } return retval; } void release_const_item_pointer(mm_const_iterator_handle_type handle) { if (!mm_const_fast_mode1()) { auto it = (*m_aux_mm_const_iterator_shptrs_ptr).find(handle.m_key); if ((*m_aux_mm_const_iterator_shptrs_ptr).end() != it) { (*m_aux_mm_const_iterator_shptrs_ptr).erase(it); } else { /* Do we need to throw here? */ MSE_THROW(msevector_range_error("invalid handle - void release_aux_mm_const_iterator(mm_const_iterator_handle_type handle) - msevector::mm_iterator_set_type")); } } else { int found_index = -1; for (int i = 0; i < m_fm1_num_mm_const_iterators; i += 1) { if (handle.m_key == m_fm1_key_mm_const_it_array[i].first) { found_index = i; break; } } if (0 <= found_index) { m_fm1_num_mm_const_iterators -= 1; assert(0 <= m_fm1_num_mm_const_iterators); for (int j = found_index; j < m_fm1_num_mm_const_iterators; j += 1) { m_fm1_key_mm_const_it_array[j] = m_fm1_key_mm_const_it_array[j + 1]; } } else { /* Do we need to throw here? */ MSE_THROW(msevector_range_error("invalid handle - void release_aux_mm_const_iterator(mm_const_iterator_handle_type handle) - msevector::mm_iterator_set_type")); } } } mm_iterator_handle_type allocate_new_item_pointer() { //auto shptr = std::shared_ptr(new mm_iterator_type(*m_owner_ptr)); auto shptr = std::make_shared(*m_owner_ptr); auto key = m_next_available_key; m_next_available_key++; mm_iterator_handle_type retval(key, shptr); typename CMMIterators::value_type new_item(key, shptr); if (!mm_fast_mode1()) { (*m_aux_mm_iterator_shptrs_ptr).insert(new_item); } else { if (sc_fm1_max_mm_iterators == m_fm1_num_mm_iterators) { /* Too many items. Initiate and switch to slow mode. */ /* Initialize slow storage. */ m_aux_mm_iterator_shptrs_ptr = new CMMIterators(); /* First copy the items from fast storage to slow storage. */ for (int i = 0; i < sc_fm1_max_mm_iterators; i += 1) { (*m_aux_mm_iterator_shptrs_ptr).insert(m_fm1_key_mm_it_array[i]); } /* Add the new items to slow storage. */ (*m_aux_mm_iterator_shptrs_ptr).insert(new_item); } else { m_fm1_key_mm_it_array[m_fm1_num_mm_iterators] = new_item; m_fm1_num_mm_iterators += 1; } } return retval; } void release_item_pointer(mm_iterator_handle_type handle) { if (!mm_fast_mode1()) { auto it = (*m_aux_mm_iterator_shptrs_ptr).find(handle.m_key); if ((*m_aux_mm_iterator_shptrs_ptr).end() != it) { (*m_aux_mm_iterator_shptrs_ptr).erase(it); } else { /* Do we need to throw here? */ MSE_THROW(msevector_range_error("invalid handle - void release_aux_mm_iterator(mm_iterator_handle_type handle) - msevector::mm_iterator_set_type")); } } else { int found_index = -1; for (int i = 0; i < m_fm1_num_mm_iterators; i += 1) { if (handle.m_key == m_fm1_key_mm_it_array[i].first) { found_index = i; break; } } if (0 <= found_index) { m_fm1_num_mm_iterators -= 1; assert(0 <= m_fm1_num_mm_iterators); for (int j = found_index; j < m_fm1_num_mm_iterators; j += 1) { m_fm1_key_mm_it_array[j] = m_fm1_key_mm_it_array[j + 1]; } } else { /* Do we need to throw here? */ MSE_THROW(msevector_range_error("invalid handle - void release_aux_mm_iterator(mm_iterator_handle_type handle) - msevector::mm_iterator_set_type")); } } } void release_all_item_pointers() { if (!mm_fast_mode1()) { (*m_aux_mm_iterator_shptrs_ptr).clear(); } else { for (int i = 0; i < m_fm1_num_mm_iterators; i += 1) { m_fm1_key_mm_it_array[i] = assignable_CMMIterators_value_type(); } m_fm1_num_mm_iterators = 0; } } mm_const_iterator_type &const_item_pointer(mm_const_iterator_handle_type handle) const { return (*(handle.m_shptr)); } mm_iterator_type &item_pointer(mm_iterator_handle_type handle) { return (*(handle.m_shptr)); } private: void release_all_const_item_pointers() { if (!mm_const_fast_mode1()) { (*m_aux_mm_const_iterator_shptrs_ptr).clear(); } else { for (int i = 0; i < m_fm1_num_mm_const_iterators; i += 1) { m_fm1_key_mm_const_it_array[i] = assignable_CMMConstIterators_value_type(); } m_fm1_num_mm_const_iterators = 0; } } mm_iterator_set_type& operator=(const mm_iterator_set_type& src_cref) { /* This is a special type of class. The state (i.e. member values) of an object of this class is specific to (and only valid for) the particular instance of the object (or the object of which it is a member). So the correct state of a new copy of this type of object is not a copy of the state, but rather the state of a new object (which is just the default initialization state). */ (*this).reset(); return (*this); } mm_iterator_set_type& operator=(mm_iterator_set_type&& src) { /* see above */ (*this).reset(); return (*this); } mm_iterator_set_type(const mm_iterator_set_type& src) { /* see above */ } mm_iterator_set_type(const mm_iterator_set_type&& src) { /* see above */ } CHashKey1 m_next_available_key = 0; static const int sc_fm1_max_mm_iterators = 6/*arbitrary*/; bool mm_const_fast_mode1() const { return (nullptr == m_aux_mm_const_iterator_shptrs_ptr); } int m_fm1_num_mm_const_iterators = 0; assignable_CMMConstIterators_value_type m_fm1_key_mm_const_it_array[sc_fm1_max_mm_iterators]; CMMConstIterators* m_aux_mm_const_iterator_shptrs_ptr = nullptr; bool mm_fast_mode1() const { return (nullptr == m_aux_mm_iterator_shptrs_ptr); } int m_fm1_num_mm_iterators = 0; assignable_CMMIterators_value_type m_fm1_key_mm_it_array[sc_fm1_max_mm_iterators]; CMMIterators* m_aux_mm_iterator_shptrs_ptr = nullptr; _Myt* m_owner_ptr = nullptr; friend class /*_Myt*/msevector<_Ty, _A>; }; mutable mm_iterator_set_type m_mmitset; public: mm_const_iterator_type &const_item_pointer(mm_const_iterator_handle_type handle) const { return m_mmitset.const_item_pointer(handle); } mm_iterator_type &item_pointer(mm_iterator_handle_type handle) { return m_mmitset.item_pointer(handle); } private: mm_const_iterator_handle_type allocate_new_const_item_pointer() const { return m_mmitset.allocate_new_const_item_pointer(); } void release_const_item_pointer(mm_const_iterator_handle_type handle) const { m_mmitset.release_const_item_pointer(handle); } void release_all_const_item_pointers() const { m_mmitset.release_all_const_item_pointers(); } mm_iterator_handle_type allocate_new_item_pointer() const { return m_mmitset.allocate_new_item_pointer(); } void release_item_pointer(mm_iterator_handle_type handle) const { m_mmitset.release_item_pointer(handle); } void release_all_item_pointers() const { m_mmitset.release_all_item_pointers(); } public: class cipointer : public random_access_const_iterator_base { public: typedef typename mm_const_iterator_type::iterator_category iterator_category; typedef typename mm_const_iterator_type::value_type value_type; typedef typename mm_const_iterator_type::difference_type difference_type; typedef difference_type distance_type; // retained typedef typename mm_const_iterator_type::pointer pointer; typedef typename mm_const_iterator_type::const_pointer const_pointer; typedef typename mm_const_iterator_type::reference reference; typedef typename mm_const_iterator_type::const_reference const_reference; cipointer(const _Myt& owner_cref) : m_owner_cptr(&owner_cref) { mm_const_iterator_handle_type handle = m_owner_cptr->allocate_new_const_item_pointer(); m_handle_shptr = std::make_shared(handle); } cipointer(const cipointer& src_cref) : m_owner_cptr(src_cref.m_owner_cptr) { mm_const_iterator_handle_type handle = m_owner_cptr->allocate_new_const_item_pointer(); m_handle_shptr = std::make_shared(handle); const_item_pointer() = src_cref.const_item_pointer(); } ~cipointer() { m_owner_cptr->release_const_item_pointer(*m_handle_shptr); } mm_const_iterator_type& const_item_pointer() const { return m_owner_cptr->const_item_pointer(*m_handle_shptr); } mm_const_iterator_type& cip() const { return const_item_pointer(); } //const mm_const_iterator_handle_type& handle() const { return (*m_handle_shptr); } void reset() { const_item_pointer().reset(); } bool points_to_an_item() const { return const_item_pointer().points_to_an_item(); } bool points_to_end_marker() const { return const_item_pointer().points_to_end_marker(); } bool points_to_beginning() const { return const_item_pointer().points_to_beginning(); } /* has_next_item_or_end_marker() is just an alias for points_to_an_item(). */ bool has_next_item_or_end_marker() const { return const_item_pointer().has_next_item_or_end_marker(); } /* has_next() is just an alias for points_to_an_item() that's familiar to java programmers. */ bool has_next() const { return const_item_pointer().has_next(); } bool has_previous() const { return const_item_pointer().has_previous(); } void set_to_beginning() { const_item_pointer().set_to_beginning(); } void set_to_end_marker() { const_item_pointer().set_to_end_marker(); } void set_to_next() { const_item_pointer().set_to_next(); } void set_to_previous() { const_item_pointer().set_to_previous(); } cipointer& operator ++() { const_item_pointer().operator ++(); return (*this); } cipointer operator++(int) { cipointer _Tmp = *this; ++*this; return (_Tmp); } cipointer& operator --() { const_item_pointer().operator --(); return (*this); } cipointer operator--(int) { cipointer _Tmp = *this; --*this; return (_Tmp); } void advance(difference_type n) { const_item_pointer().advance(n); } void regress(difference_type n) { const_item_pointer().regress(n); } cipointer& operator +=(difference_type n) { const_item_pointer().operator +=(n); return (*this); } cipointer& operator -=(difference_type n) { const_item_pointer().operator -=(n); return (*this); } cipointer operator+(difference_type n) const { auto retval = (*this); retval += n; return retval; } cipointer operator-(difference_type n) const { return ((*this) + (-n)); } difference_type operator-(const cipointer& _Right_cref) const { return const_item_pointer() - (_Right_cref.const_item_pointer()); } const_reference operator*() const { return const_item_pointer().operator*(); } const_reference item() const { return operator*(); } const_reference previous_item() const { return const_item_pointer().previous_item(); } const_pointer operator->() const { return const_item_pointer().operator->(); } const_reference operator[](difference_type _Off) const { return const_item_pointer()[_Off]; } cipointer& operator=(const cipointer& _Right_cref) { const_item_pointer().operator=(_Right_cref.const_item_pointer()); return (*this); } bool operator==(const cipointer& _Right_cref) const { return const_item_pointer().operator==(_Right_cref.const_item_pointer()); } bool operator!=(const cipointer& _Right_cref) const { return (!(_Right_cref == (*this))); } bool operator<(const cipointer& _Right) const { return (const_item_pointer() < _Right.const_item_pointer()); } bool operator<=(const cipointer& _Right) const { return (const_item_pointer() <= _Right.const_item_pointer()); } bool operator>(const cipointer& _Right) const { return (const_item_pointer() > _Right.const_item_pointer()); } bool operator>=(const cipointer& _Right) const { return (const_item_pointer() >= _Right.const_item_pointer()); } void set_to_const_item_pointer(const cipointer& _Right_cref) { const_item_pointer().set_to_const_item_pointer(_Right_cref.const_item_pointer()); } msev_size_t position() const { return const_item_pointer().position(); } private: const _Myt* m_owner_cptr = nullptr; std::shared_ptr m_handle_shptr; friend class /*_Myt*/msevector<_Ty, _A>; }; class ipointer : public random_access_iterator_base { public: typedef typename mm_iterator_type::iterator_category iterator_category; typedef typename mm_iterator_type::value_type value_type; typedef typename mm_iterator_type::difference_type difference_type; typedef difference_type distance_type; // retained typedef typename mm_iterator_type::pointer pointer; typedef typename mm_iterator_type::reference reference; ipointer(_Myt& owner_ref) : m_owner_ptr(&owner_ref) { mm_iterator_handle_type handle = m_owner_ptr->allocate_new_item_pointer(); m_handle_shptr = std::make_shared(handle); } ipointer(const ipointer& src_cref) : m_owner_ptr(src_cref.m_owner_ptr) { mm_iterator_handle_type handle = m_owner_ptr->allocate_new_item_pointer(); m_handle_shptr = std::make_shared(handle); item_pointer() = src_cref.item_pointer(); } ~ipointer() { m_owner_ptr->release_item_pointer(*m_handle_shptr); } mm_iterator_type& item_pointer() const { return m_owner_ptr->item_pointer(*m_handle_shptr); } mm_iterator_type& ip() const { return item_pointer(); } //const mm_iterator_handle_type& handle() const { return (*m_handle_shptr); } operator cipointer() const { cipointer retval(*m_owner_ptr); retval.const_item_pointer().set_to_beginning(); retval.const_item_pointer().advance(msev_int(item_pointer().position())); return retval; } void reset() { item_pointer().reset(); } bool points_to_an_item() const { return item_pointer().points_to_an_item(); } bool points_to_end_marker() const { return item_pointer().points_to_end_marker(); } bool points_to_beginning() const { return item_pointer().points_to_beginning(); } /* has_next_item_or_end_marker() is just an alias for points_to_an_item(). */ bool has_next_item_or_end_marker() const { return item_pointer().has_next_item_or_end_marker(); } /* has_next() is just an alias for points_to_an_item() that's familiar to java programmers. */ bool has_next() const { return item_pointer().has_next(); } bool has_previous() const { return item_pointer().has_previous(); } void set_to_beginning() { item_pointer().set_to_beginning(); } void set_to_end_marker() { item_pointer().set_to_end_marker(); } void set_to_next() { item_pointer().set_to_next(); } void set_to_previous() { item_pointer().set_to_previous(); } ipointer& operator ++() { item_pointer().operator ++(); return (*this); } ipointer operator++(int) { ipointer _Tmp = *this; ++*this; return (_Tmp); } ipointer& operator --() { item_pointer().operator --(); return (*this); } ipointer operator--(int) { ipointer _Tmp = *this; --*this; return (_Tmp); } void advance(difference_type n) { item_pointer().advance(n); } void regress(difference_type n) { item_pointer().regress(n); } ipointer& operator +=(difference_type n) { item_pointer().operator +=(n); return (*this); } ipointer& operator -=(difference_type n) { item_pointer().operator -=(n); return (*this); } ipointer operator+(difference_type n) const { auto retval = (*this); retval += n; return retval; } ipointer operator-(difference_type n) const { return ((*this) + (-n)); } difference_type operator-(const ipointer& _Right_cref) const { return item_pointer() - (_Right_cref.item_pointer()); } reference operator*() const { return item_pointer().operator*(); } reference item() const { return operator*(); } reference previous_item() const { return item_pointer().previous_item(); } pointer operator->() const { return item_pointer().operator->(); } reference operator[](difference_type _Off) const { return item_pointer()[_Off]; } ipointer& operator=(const ipointer& _Right_cref) { item_pointer().operator=(_Right_cref.item_pointer()); return (*this); } bool operator==(const ipointer& _Right_cref) const { return item_pointer().operator==(_Right_cref.item_pointer()); } bool operator!=(const ipointer& _Right_cref) const { return (!(_Right_cref == (*this))); } bool operator<(const ipointer& _Right) const { return (item_pointer() < _Right.item_pointer()); } bool operator<=(const ipointer& _Right) const { return (item_pointer() <= _Right.item_pointer()); } bool operator>(const ipointer& _Right) const { return (item_pointer() > _Right.item_pointer()); } bool operator>=(const ipointer& _Right) const { return (item_pointer() >= _Right.item_pointer()); } void set_to_item_pointer(const ipointer& _Right_cref) { item_pointer().set_to_item_pointer(_Right_cref.item_pointer()); } msev_size_t position() const { return item_pointer().position(); } private: _Myt* m_owner_ptr = nullptr; std::shared_ptr m_handle_shptr; friend class /*_Myt*/msevector<_Ty, _A>; }; ipointer ibegin() { // return ipointer for beginning of mutable sequence ipointer retval(*this); retval.set_to_beginning(); return retval; } cipointer ibegin() const { // return ipointer for beginning of nonmutable sequence cipointer retval(*this); retval.set_to_beginning(); return retval; } ipointer iend() { // return ipointer for end of mutable sequence ipointer retval(*this); retval.set_to_end_marker(); return retval; } cipointer iend() const { // return ipointer for end of nonmutable sequence cipointer retval(*this); retval.set_to_end_marker(); return retval; } cipointer cibegin() const { // return ipointer for beginning of nonmutable sequence cipointer retval(*this); retval.set_to_beginning(); return retval; } cipointer ciend() const { // return ipointer for end of nonmutable sequence cipointer retval(*this); retval.set_to_end_marker(); return retval; } msevector(const cipointer &start, const cipointer &end, const _A& _Al = _A()) : base_class(_Al), m_mmitset(*this) { /*m_debug_size = size();*/ assign(start, end); } void assign(const mm_const_iterator_type &start, const mm_const_iterator_type &end) { if (start.m_owner_cptr != end.m_owner_cptr) { MSE_THROW(msevector_range_error("invalid arguments - void assign(const mm_const_iterator_type &start, const mm_const_iterator_type &end) - msevector")); } if (start > end) { MSE_THROW(msevector_range_error("invalid arguments - void assign(const mm_const_iterator_type &start, const mm_const_iterator_type &end) - msevector")); } typename base_class::const_iterator _F = start; typename base_class::const_iterator _L = end; (*this).assign(_F, _L); } void assign_inclusive(const mm_const_iterator_type &first, const mm_const_iterator_type &last) { auto end = last; end++; // this should include some checks (*this).assign(first, end); } void assign(const cipointer &start, const cipointer &end) { assign(start.const_item_pointer(), end.const_item_pointer()); } void assign_inclusive(const cipointer &first, const cipointer &last) { assign_inclusive(first.const_item_pointer(), last.const_item_pointer()); } void insert_before(const mm_const_iterator_type &pos, size_type _M, const _Ty& _X) { if (pos.m_owner_cptr != this) { MSE_THROW(msevector_range_error("invalid arguments - void insert_before() - msevector")); } typename base_class::const_iterator _P = pos; (*this).insert(_P, _M, _X); } void insert_before(const mm_const_iterator_type &pos, _Ty&& _X) { if (pos.m_owner_cptr != this) { MSE_THROW(msevector_range_error("invalid arguments - void insert_before() - msevector")); } typename base_class::const_iterator _P = pos; (*this).insert(_P, 1, std::move(_X)); } void insert_before(const mm_const_iterator_type &pos, const _Ty& _X = _Ty()) { (*this).insert(pos, 1, _X); } templatetypename std::enable_if<_mse_Is_iterator<_Iter>::value, typename base_class::iterator>::type , class = _mse_RequireInputIter<_Iter> > void insert_before(const mm_const_iterator_type &pos, const _Iter &start, const _Iter &end) { if (pos.m_owner_cptr != this) { MSE_THROW(msevector_range_error("invalid arguments - void insert_before() - msevector")); } //if (start.m_owner_cptr != end.m_owner_cptr) { MSE_THROW(msevector_range_error("invalid arguments - void insert_before(const mm_const_iterator_type &pos, const mm_const_iterator_type &start, const mm_const_iterator_type &end) - msevector")); } typename base_class::const_iterator _P = pos; (*this).insert(_P, start, end); } templatetypename std::enable_if<_mse_Is_iterator<_Iter>::value, typename base_class::iterator>::type , class = _mse_RequireInputIter<_Iter> > void insert_before_inclusive(const mm_const_iterator_type &pos, const _Iter &first, const _Iter &last) { if (pos.m_owner_cptr != this) { MSE_THROW(msevector_range_error("invalid arguments - void insert_before() - msevector")); } if (first.m_owner_cptr != last.m_owner_cptr) { MSE_THROW(msevector_range_error("invalid arguments - void insert_before_inclusive(const mm_const_iterator_type &pos, const mm_const_iterator_type &first, const mm_const_iterator_type &last) - msevector")); } if (!(last.points_to_item())) { MSE_THROW(msevector_range_error("invalid argument - void insert_before_inclusive(const mm_const_iterator_type &pos, const mm_const_iterator_type &first, const mm_const_iterator_type &last) - msevector")); } typename base_class::const_iterator _P = pos; auto _L = last; _L++; (*this).insert(_P, first, _L); } void insert_before(const mm_const_iterator_type &pos, _XSTD initializer_list _Ilist) { // insert initializer_list if (pos.m_owner_cptr != this) { MSE_THROW(msevector_range_error("invalid arguments - void insert_before() - msevector")); } typename base_class::const_iterator _P = pos; (*this).insert(_P, _Ilist); } ipointer insert_before(const cipointer &pos, size_type _M, const _Ty& _X) { msev_size_t original_pos = pos.position(); insert_before(pos.const_item_pointer(), _M, _X); ipointer retval(*this); retval.advance(msev_int(original_pos)); return retval; } ipointer insert_before(const cipointer &pos, _Ty&& _X) { msev_size_t original_pos = pos.position(); insert_before(pos.const_item_pointer(), std::move(_X)); ipointer retval(*this); retval.advance(msev_int(original_pos)); return retval; } ipointer insert_before(const cipointer &pos, const _Ty& _X = _Ty()) { return insert_before(pos, 1, _X); } templatetypename std::enable_if<_mse_Is_iterator<_Iter>::value, typename base_class::iterator>::type , class = _mse_RequireInputIter<_Iter> > ipointer insert_before(const cipointer &pos, const _Iter &start, const _Iter &end) { msev_size_t original_pos = pos.position(); insert_before(pos.const_item_pointer(), start, end); ipointer retval(*this); retval.advance(msev_int(original_pos)); return retval; } templatetypename std::enable_if<_mse_Is_iterator<_Iter>::value, typename base_class::iterator>::type , class = _mse_RequireInputIter<_Iter> > ipointer insert_before_inclusive(const cipointer &pos, const _Iter &first, const _Iter &last) { auto end = last; end++; return insert_before(pos, first, end); } ipointer insert_before(const cipointer &pos, _XSTD initializer_list _Ilist) { // insert initializer_list msev_size_t original_pos = pos.position(); (*this).insert_before(pos.const_item_pointer(), _Ilist); ipointer retval(*this); retval.advance(msev_int(original_pos)); return retval; } void insert_before(msev_size_t pos, _Ty&& _X) { typename base_class::const_iterator _P = (*this).begin() + msev_as_a_size_t(pos); (*this).insert(_P, std::move(_X)); } void insert_before(msev_size_t pos, const _Ty& _X = _Ty()) { typename base_class::const_iterator _P = (*this).begin() + msev_as_a_size_t(pos); (*this).insert(_P, _X); } void insert_before(msev_size_t pos, size_t _M, const _Ty& _X) { typename base_class::const_iterator _P = (*this).begin() + msev_as_a_size_t(pos); (*this).insert(_P, _M, _X); } void insert_before(msev_size_t pos, _XSTD initializer_list _Ilist) { // insert initializer_list typename base_class::const_iterator _P = (*this).begin() + msev_as_a_size_t(pos); (*this).insert(_P, _Ilist); } /* These insert() functions are just aliases for their corresponding insert_before() functions. */ ipointer insert(const cipointer &pos, size_type _M, const _Ty& _X) { return insert_before(pos, _M, _X); } ipointer insert(const cipointer &pos, _Ty&& _X) { return insert_before(pos, std::move(_X)); } ipointer insert(const cipointer &pos, const _Ty& _X = _Ty()) { return insert_before(pos, _X); } templatetypename std::enable_if<_mse_Is_iterator<_Iter>::value, typename base_class::iterator>::type , class = _mse_RequireInputIter<_Iter> > ipointer insert(const cipointer &pos, const _Iter &start, const _Iter &end) { return insert_before(pos, start, end); } ipointer insert(const cipointer &pos, _XSTD initializer_list _Ilist) { return insert_before(pos, _Ilist); } template #if !(defined(GPP4P8_COMPATIBLE)) void emplace(const mm_const_iterator_type &pos, _Valty&& ..._Val) { // insert by moving _Val at pos #else /*!(defined(GPP4P8_COMPATIBLE))*/ void emplace(const mm_iterator_type &pos, _Valty&& ..._Val) { // insert by moving _Val at pos #endif /*!(defined(GPP4P8_COMPATIBLE))*/ if (pos.m_owner_cptr != this) { MSE_THROW(msevector_range_error("invalid arguments - void emplace() - msevector")); } typename base_class::const_iterator _P = pos; auto retval = base_class::emplace(_P, std::forward<_Valty>(_Val)...); } template #if !(defined(GPP4P8_COMPATIBLE)) ipointer emplace(const cipointer &pos, _Valty&& ..._Val) { // insert by moving _Val at pos #else /*!(defined(GPP4P8_COMPATIBLE))*/ ipointer emplace(const ipointer &pos, _Valty&& ..._Val) { // insert by moving _Val at pos #endif /*!(defined(GPP4P8_COMPATIBLE))*/ msev_size_t original_pos = pos.position(); (*this).emplace(pos.const_item_pointer(), std::forward<_Valty>(_Val)...); ipointer retval(*this); retval.advance(msev_int(original_pos)); return retval; } void erase(const mm_const_iterator_type &pos) { if (pos.m_owner_cptr != this) { MSE_THROW(msevector_range_error("invalid arguments - void erase() - msevector")); } typename base_class::const_iterator _P = pos; (*this).erase(_P); } void erase(const mm_const_iterator_type &start, const mm_const_iterator_type &end) { if (start.m_owner_cptr != this) { MSE_THROW(msevector_range_error("invalid arguments - void erase() - msevector")); } if (end.m_owner_cptr != this) { MSE_THROW(msevector_range_error("invalid arguments - void erase() - msevector")); } typename base_class::const_iterator _F = start; typename base_class::const_iterator _L = end; (*this).erase(_F, _L); } void erase_inclusive(const mm_const_iterator_type &first, const mm_const_iterator_type &last) { if (first.m_owner_cptr != this) { MSE_THROW(msevector_range_error("invalid arguments - void erase_inclusive() - msevector")); } if (last.m_owner_cptr != this) { MSE_THROW(msevector_range_error("invalid arguments - void erase_inclusive() - msevector")); } if (!(last.points_to_item())) { MSE_THROW(msevector_range_error("invalid argument - void erase_inclusive() - msevector")); } typename base_class::const_iterator _F = first; typename base_class::const_iterator _L = last; _L++; (*this).erase(_F, _L); } ipointer erase(const cipointer &pos) { auto retval_pos = pos; retval_pos.set_to_next(); erase(pos.const_item_pointer()); ipointer retval = (*this).ibegin(); retval.advance(msev_int(retval_pos.position())); return retval; } ipointer erase(const cipointer &start, const cipointer &end) { auto retval_pos = end; retval_pos.set_to_next(); erase(start.const_item_pointer(), end.const_item_pointer()); ipointer retval = (*this).ibegin(); retval.advance(msev_int(retval_pos.position())); return retval; } ipointer erase_inclusive(const cipointer &first, const cipointer &last) { auto end = last; end.set_to_next(); return erase(first, end); } void erase_previous_item(const mm_const_iterator_type &pos) { if (pos.m_owner_cptr != this) { MSE_THROW(msevector_range_error("invalid arguments - void erase_previous_item() - msevector")); } if (!(pos.has_previous())) { MSE_THROW(msevector_range_error("invalid arguments - void erase_previous_item() - msevector")); } typename base_class::const_iterator _P = pos; _P--; (*this).erase(_P); } ipointer erase_previous_item(const cipointer &pos) { erase_previous_item(pos.const_item_pointer()); ipointer retval = (*this).ibegin(); retval.advance(pos.position()); return retval; } /* ss_const_iterator_type is a bounds checked iterator. */ class ss_const_iterator_type : public random_access_const_iterator_base { public: typedef typename base_class::const_iterator::iterator_category iterator_category; typedef typename base_class::const_iterator::value_type value_type; //typedef typename base_class::const_iterator::difference_type difference_type; typedef typename _Myt::difference_type difference_type; typedef difference_type distance_type; // retained typedef typename base_class::const_iterator::pointer pointer; typedef typename base_class::const_pointer const_pointer; typedef typename base_class::const_iterator::reference reference; typedef typename base_class::const_reference const_reference; ss_const_iterator_type() {} void assert_valid_index() const { if (m_owner_cptr->size() < m_index) { MSE_THROW(msevector_range_error("invalid index - void assert_valid_index() const - ss_const_iterator_type - msevector")); } } void reset() { set_to_end_marker(); } bool points_to_an_item() const { if (m_owner_cptr->size() > m_index) { return true; } else { if (m_index == m_owner_cptr->size()) { return false; } else { MSE_THROW(msevector_range_error("attempt to use invalid ss_const_iterator_type - bool points_to_an_item() const - ss_const_iterator_type - msevector")); } } } bool points_to_end_marker() const { if (false == points_to_an_item()) { assert(m_index == m_owner_cptr->size()); return true; } else { return false; } } bool points_to_beginning() const { if (0 == m_index) { return true; } else { return false; } } /* has_next_item_or_end_marker() is just an alias for points_to_an_item(). */ bool has_next_item_or_end_marker() const { return points_to_an_item(); } /* has_next() is just an alias for points_to_an_item() that's familiar to java programmers. */ bool has_next() const { return has_next_item_or_end_marker(); } bool has_previous() const { if (m_owner_cptr->size() < m_index) { MSE_THROW(msevector_range_error("attempt to use invalid ss_const_iterator_type - bool has_previous() const - ss_const_iterator_type - msevector")); } else if (1 <= m_index) { return true; } else { return false; } } void set_to_beginning() { m_index = 0; } void set_to_end_marker() { m_index = m_owner_cptr->size(); } void set_to_next() { if (points_to_an_item()) { m_index += 1; } else { MSE_THROW(msevector_range_error("attempt to use invalid const_item_pointer - void set_to_next() - ss_const_iterator_type - msevector")); } } void set_to_previous() { if (has_previous()) { m_index -= 1; } else { MSE_THROW(msevector_range_error("attempt to use invalid const_item_pointer - void set_to_previous() - ss_const_iterator_type - msevector")); } } ss_const_iterator_type& operator ++() { (*this).set_to_next(); return (*this); } ss_const_iterator_type operator++(int) { ss_const_iterator_type _Tmp = *this; (*this).set_to_next(); return (_Tmp); } ss_const_iterator_type& operator --() { (*this).set_to_previous(); return (*this); } ss_const_iterator_type operator--(int) { ss_const_iterator_type _Tmp = *this; (*this).set_to_previous(); return (_Tmp); } void advance(difference_type n) { auto new_index = msev_int(m_index) + n; if ((0 > new_index) || (m_owner_cptr->size() < msev_size_t(new_index))) { MSE_THROW(msevector_range_error("index out of range - void advance(difference_type n) - ss_const_iterator_type - msevector")); } else { m_index = msev_size_t(new_index); } } void regress(difference_type n) { advance(-n); } ss_const_iterator_type& operator +=(difference_type n) { (*this).advance(n); return (*this); } ss_const_iterator_type& operator -=(difference_type n) { (*this).regress(n); return (*this); } ss_const_iterator_type operator+(difference_type n) const { ss_const_iterator_type retval; retval.m_owner_cptr = m_owner_cptr; retval = (*this); retval.advance(n); return retval; } ss_const_iterator_type operator-(difference_type n) const { return ((*this) + (-n)); } difference_type operator-(const ss_const_iterator_type &rhs) const { if (rhs.m_owner_cptr != (*this).m_owner_cptr) { MSE_THROW(msevector_range_error("invalid argument - difference_type operator-(const ss_const_iterator_type &rhs) const - msevector::ss_const_iterator_type")); } auto retval = difference_type((*this).m_index) - difference_type(rhs.m_index); assert(difference_type((*m_owner_cptr).size()) >= retval); return retval; } const_reference operator*() const { return (*m_owner_cptr).at(msev_as_a_size_t((*this).m_index)); } const_reference item() const { return operator*(); } const_reference previous_item() const { return m_owner_cptr->at(msev_as_a_size_t(m_index - 1)); } const_pointer operator->() const { return &((*m_owner_cptr).at(msev_as_a_size_t((*this).m_index))); } const_reference operator[](difference_type _Off) const { return (*m_owner_cptr).at(msev_as_a_size_t(difference_type(m_index) + _Off)); } /* ss_const_iterator_type& operator=(const typename base_class::const_iterator& _Right_cref) { msev_int d = std::distance(m_owner_cptr->cbegin(), _Right_cref); if ((0 <= d) && (m_owner_cptr->size() >= d)) { if (m_owner_cptr->size() == d) { assert(m_owner_cptr->cend() == _Right_cref); } m_index = msev_size_t(d); base_class::const_iterator::operator=(_Right_cref); } else { MSE_THROW(msevector_range_error("doesn't seem to be a valid assignment value - ss_const_iterator_type& operator=(const typename base_class::const_iterator& _Right_cref) - ss_const_iterator_type - msevector")); } return (*this); } */ ss_const_iterator_type& operator=(const ss_const_iterator_type& _Right_cref) { ((*this).m_owner_cptr) = _Right_cref.m_owner_cptr; (*this).m_index = _Right_cref.m_index; return (*this); } bool operator==(const ss_const_iterator_type& _Right_cref) const { if (this->m_owner_cptr != _Right_cref.m_owner_cptr) { MSE_THROW(msevector_range_error("invalid argument - ss_const_iterator_type& operator==(const ss_const_iterator_type& _Right) - ss_const_iterator_type - msevector")); } return (_Right_cref.m_index == m_index); } bool operator!=(const ss_const_iterator_type& _Right_cref) const { return (!(_Right_cref == (*this))); } bool operator<(const ss_const_iterator_type& _Right) const { if (this->m_owner_cptr != _Right.m_owner_cptr) { MSE_THROW(msevector_range_error("invalid argument - ss_const_iterator_type& operator<(const ss_const_iterator_type& _Right) - ss_const_iterator_type - msevector")); } return (m_index < _Right.m_index); } bool operator<=(const ss_const_iterator_type& _Right) const { return (((*this) < _Right) || (_Right == (*this))); } bool operator>(const ss_const_iterator_type& _Right) const { return (!((*this) <= _Right)); } bool operator>=(const ss_const_iterator_type& _Right) const { return (!((*this) < _Right)); } void set_to_const_item_pointer(const ss_const_iterator_type& _Right_cref) { (*this) = _Right_cref; } void invalidate_inclusive_range(msev_size_t index_of_first, msev_size_t index_of_last) { if ((index_of_first <= (*this).m_index) && (index_of_last >= (*this).m_index)) { (*this).reset(); } } void shift_inclusive_range(msev_size_t index_of_first, msev_size_t index_of_last, msev_int shift) { if ((index_of_first <= (*this).m_index) && (index_of_last >= (*this).m_index)) { auto new_index = (*this).m_index + shift; if ((0 > new_index) || (m_owner_cptr->size() < new_index)) { MSE_THROW(msevector_range_error("void shift_inclusive_range() - ss_const_iterator_type - msevector")); } else { (*this).m_index = msev_size_t(new_index); (*this).sync_const_iterator_to_index(); } } } msev_size_t position() const { return m_index; } operator typename base_class::const_iterator() const { typename base_class::const_iterator retval = (*m_owner_cptr).cbegin(); retval += msev_as_a_size_t(m_index); return retval; } private: void sync_const_iterator_to_index() { assert(m_owner_cptr->size() >= (*this).m_index); //base_class::const_iterator::operator=(m_owner_cptr->cbegin()); //base_class::const_iterator::operator+=(msev_as_a_size_t(m_index)); } msev_size_t m_index = 0; msev_pointer m_owner_cptr = nullptr; friend class /*_Myt*/msevector<_Ty, _A>; }; /* ss_iterator_type is a bounds checked iterator. */ class ss_iterator_type : public random_access_iterator_base { public: typedef typename base_class::iterator::iterator_category iterator_category; typedef typename base_class::iterator::value_type value_type; //typedef typename base_class::iterator::difference_type difference_type; typedef typename _Myt::difference_type difference_type; typedef difference_type distance_type; // retained typedef typename base_class::iterator::pointer pointer; typedef typename base_class::iterator::reference reference; ss_iterator_type() {} void reset() { set_to_end_marker(); } bool points_to_an_item() const { if (m_owner_ptr->size() > m_index) { return true; } else { if (m_index == m_owner_ptr->size()) { return false; } else { MSE_THROW(msevector_range_error("attempt to use invalid ss_iterator_type - bool points_to_an_item() const - ss_iterator_type - msevector")); } } } bool points_to_end_marker() const { if (false == points_to_an_item()) { assert(m_index == m_owner_ptr->size()); return true; } else { return false; } } bool points_to_beginning() const { if (0 == m_index) { return true; } else { return false; } } /* has_next_item_or_end_marker() is just an alias for points_to_an_item(). */ bool has_next_item_or_end_marker() const { return points_to_an_item(); } /* has_next() is just an alias for points_to_an_item() that's familiar to java programmers. */ bool has_next() const { return has_next_item_or_end_marker(); } bool has_previous() const { if (m_owner_ptr->size() < m_index) { MSE_THROW(msevector_range_error("attempt to use invalid ss_iterator_type - bool has_previous() const - ss_iterator_type - msevector")); } else if (1 <= m_index) { return true; } else { return false; } } void set_to_beginning() { m_index = 0; } void set_to_end_marker() { m_index = m_owner_ptr->size(); } void set_to_next() { if (points_to_an_item()) { m_index += 1; } else { MSE_THROW(msevector_range_error("attempt to use invalid item_pointer - void set_to_next() - ss_const_iterator_type - msevector")); } } void set_to_previous() { if (has_previous()) { m_index -= 1; } else { MSE_THROW(msevector_range_error("attempt to use invalid item_pointer - void set_to_previous() - ss_iterator_type - msevector")); } } ss_iterator_type& operator ++() { (*this).set_to_next(); return (*this); } ss_iterator_type operator++(int) { ss_iterator_type _Tmp = *this; (*this).set_to_next(); return (_Tmp); } ss_iterator_type& operator --() { (*this).set_to_previous(); return (*this); } ss_iterator_type operator--(int) { ss_iterator_type _Tmp = *this; (*this).set_to_previous(); return (_Tmp); } void advance(difference_type n) { auto new_index = msev_int(m_index) + n; if ((0 > new_index) || (m_owner_ptr->size() < msev_size_t(new_index))) { MSE_THROW(msevector_range_error("index out of range - void advance(difference_type n) - ss_iterator_type - msevector")); } else { m_index = msev_size_t(new_index); } } void regress(difference_type n) { advance(-n); } ss_iterator_type& operator +=(difference_type n) { (*this).advance(n); return (*this); } ss_iterator_type& operator -=(difference_type n) { (*this).regress(n); return (*this); } ss_iterator_type operator+(difference_type n) const { ss_iterator_type retval; retval.m_owner_ptr = m_owner_ptr; retval = (*this); retval.advance(n); return retval; } ss_iterator_type operator-(difference_type n) const { return ((*this) + (-n)); } difference_type operator-(const ss_iterator_type& rhs) const { if (rhs.m_owner_ptr != (*this).m_owner_ptr) { MSE_THROW(msevector_range_error("invalid argument - difference_type operator-(const ss_iterator_type& rhs) const - msevector::ss_iterator_type")); } auto retval = difference_type((*this).m_index) - difference_type(rhs.m_index); assert(int((*m_owner_ptr).size()) >= retval); return retval; } reference operator*() const { return (*m_owner_ptr).at(msev_as_a_size_t((*this).m_index)); } reference item() const { return operator*(); } reference previous_item() const { return m_owner_ptr->at(msev_as_a_size_t(m_index - 1)); } pointer operator->() const { return &((*m_owner_ptr).at(msev_as_a_size_t((*this).m_index))); } reference operator[](difference_type _Off) const { return (*m_owner_ptr).at(msev_as_a_size_t(difference_type(m_index) + _Off)); } /* ss_iterator_type& operator=(const typename base_class::iterator& _Right_cref) { msev_int d = std::distance(m_owner_ptr->begin(), _Right_cref); if ((0 <= d) && (m_owner_ptr->size() >= d)) { if (m_owner_ptr->size() == d) { assert(m_owner_ptr->end() == _Right_cref); } m_index = msev_size_t(d); base_class::iterator::operator=(_Right_cref); } else { MSE_THROW(msevector_range_error("doesn't seem to be a valid assignment value - ss_iterator_type& operator=(const typename base_class::iterator& _Right_cref) - ss_const_iterator_type - msevector")); } return (*this); } */ ss_iterator_type& operator=(const ss_iterator_type& _Right_cref) { ((*this).m_owner_ptr) = _Right_cref.m_owner_ptr; (*this).m_index = _Right_cref.m_index; return (*this); } bool operator==(const ss_iterator_type& _Right_cref) const { if (this->m_owner_ptr != _Right_cref.m_owner_ptr) { MSE_THROW(msevector_range_error("invalid argument - ss_iterator_type& operator==(const ss_iterator_type& _Right) - ss_iterator_type - msevector")); } return (_Right_cref.m_index == m_index); } bool operator!=(const ss_iterator_type& _Right_cref) const { return (!(_Right_cref == (*this))); } bool operator<(const ss_iterator_type& _Right) const { if (this->m_owner_ptr != _Right.m_owner_ptr) { MSE_THROW(msevector_range_error("invalid argument - ss_iterator_type& operator<(const ss_iterator_type& _Right) - ss_iterator_type - msevector")); } return (m_index < _Right.m_index); } bool operator<=(const ss_iterator_type& _Right) const { return (((*this) < _Right) || (_Right == (*this))); } bool operator>(const ss_iterator_type& _Right) const { return (!((*this) <= _Right)); } bool operator>=(const ss_iterator_type& _Right) const { return (!((*this) < _Right)); } void set_to_item_pointer(const ss_iterator_type& _Right_cref) { (*this) = _Right_cref; } void invalidate_inclusive_range(msev_size_t index_of_first, msev_size_t index_of_last) { if ((index_of_first <= (*this).m_index) && (index_of_last >= (*this).m_index)) { (*this).reset(); } } void shift_inclusive_range(msev_size_t index_of_first, msev_size_t index_of_last, msev_int shift) { if ((index_of_first <= (*this).m_index) && (index_of_last >= (*this).m_index)) { auto new_index = (*this).m_index + shift; if ((0 > new_index) || (m_owner_ptr->size() < new_index)) { MSE_THROW(msevector_range_error("void shift_inclusive_range() - ss_iterator_type - msevector")); } else { (*this).m_index = msev_size_t(new_index); (*this).sync_iterator_to_index(); } } } msev_size_t position() const { return m_index; } operator ss_const_iterator_type() const { ss_const_iterator_type retval; if (nullptr != m_owner_ptr) { retval = m_owner_ptr->ss_cbegin(); retval.advance(msev_int(m_index)); } return retval; } operator typename base_class::iterator() const { typename base_class::iterator retval = (*m_owner_ptr).begin(); retval += msev_as_a_size_t(m_index); return retval; } private: void sync_iterator_to_index() { assert(m_owner_ptr->size() >= (*this).m_index); //base_class::iterator::operator=(m_owner_ptr->begin()); //base_class::iterator::operator+=(msev_as_a_size_t(m_index)); } msev_size_t m_index = 0; msev_pointer<_Myt> m_owner_ptr = nullptr; friend class /*_Myt*/msevector<_Ty, _A>; }; typedef std::reverse_iterator ss_reverse_iterator_type; typedef std::reverse_iterator ss_const_reverse_iterator_type; ss_iterator_type ss_begin() { // return base_class::iterator for beginning of mutable sequence ss_iterator_type retval; retval.m_owner_ptr = this; retval.set_to_beginning(); return retval; } ss_const_iterator_type ss_begin() const { // return base_class::iterator for beginning of nonmutable sequence ss_const_iterator_type retval; retval.m_owner_cptr = this; retval.set_to_beginning(); return retval; } ss_iterator_type ss_end() { // return base_class::iterator for end of mutable sequence ss_iterator_type retval; retval.m_owner_ptr = this; retval.set_to_end_marker(); return retval; } ss_const_iterator_type ss_end() const { // return base_class::iterator for end of nonmutable sequence ss_const_iterator_type retval; retval.m_owner_cptr = this; retval.set_to_end_marker(); return retval; } ss_const_iterator_type ss_cbegin() const { // return base_class::iterator for beginning of nonmutable sequence ss_const_iterator_type retval; retval.m_owner_cptr = this; retval.set_to_beginning(); return retval; } ss_const_iterator_type ss_cend() const { // return base_class::iterator for end of nonmutable sequence ss_const_iterator_type retval; retval.m_owner_cptr = this; retval.set_to_end_marker(); return retval; } ss_const_reverse_iterator_type ss_crbegin() const { // return base_class::iterator for beginning of reversed nonmutable sequence return (ss_rbegin()); } ss_const_reverse_iterator_type ss_crend() const { // return base_class::iterator for end of reversed nonmutable sequence return (ss_rend()); } ss_reverse_iterator_type ss_rbegin() { // return base_class::iterator for beginning of reversed mutable sequence return (reverse_iterator(ss_end())); } ss_const_reverse_iterator_type ss_rbegin() const { // return base_class::iterator for beginning of reversed nonmutable sequence return (const_reverse_iterator(ss_end())); } ss_reverse_iterator_type ss_rend() { // return base_class::iterator for end of reversed mutable sequence return (reverse_iterator(ss_begin())); } ss_const_reverse_iterator_type ss_rend() const { // return base_class::iterator for end of reversed nonmutable sequence return (const_reverse_iterator(ss_begin())); } msevector(const ss_const_iterator_type &start, const ss_const_iterator_type &end, const _A& _Al = _A()) : base_class(_Al), m_mmitset(*this) { /*m_debug_size = size();*/ assign(start, end); } void assign(const ss_const_iterator_type &start, const ss_const_iterator_type &end) { if (start.m_owner_cptr != end.m_owner_cptr) { MSE_THROW(msevector_range_error("invalid arguments - void assign(const ss_const_iterator_type &start, const ss_const_iterator_type &end) - msevector")); } if (start > end) { MSE_THROW(msevector_range_error("invalid arguments - void assign(const ss_const_iterator_type &start, const ss_const_iterator_type &end) - msevector")); } typename base_class::const_iterator _F = start; typename base_class::const_iterator _L = end; (*this).assign(_F, _L); } void assign_inclusive(const ss_const_iterator_type &first, const ss_const_iterator_type &last) { auto end = last; end++; // this should include some checks (*this).assign(first, end); } ss_iterator_type insert_before(const ss_const_iterator_type &pos, size_type _M, const _Ty& _X) { if (pos.m_owner_cptr != this) { MSE_THROW(msevector_range_error("invalid argument - void insert_before() - msevector")); } pos.assert_valid_index(); msev_size_t original_pos = pos.position(); typename base_class::const_iterator _P = pos; (*this).insert(_P, _M, _X); ss_iterator_type retval = ss_begin(); retval.advance(msev_int(original_pos)); return retval; } ss_iterator_type insert_before(const ss_const_iterator_type &pos, _Ty&& _X) { if (pos.m_owner_cptr != this) { MSE_THROW(msevector_range_error("invalid argument - void insert_before() - msevector")); } pos.assert_valid_index(); msev_size_t original_pos = pos.position(); typename base_class::const_iterator _P = pos; (*this).insert(_P, std::move(_X)); ss_iterator_type retval = ss_begin(); retval.advance(msev_int(original_pos)); return retval; } ss_iterator_type insert_before(const ss_const_iterator_type &pos, const _Ty& _X = _Ty()) { return (*this).insert(pos, 1, _X); } templatetypename std::enable_if<_mse_Is_iterator<_Iter>::value, typename base_class::iterator>::type , class = _mse_RequireInputIter<_Iter> > ss_iterator_type insert_before(const ss_const_iterator_type &pos, const _Iter &start, const _Iter &end) { if (pos.m_owner_cptr != this) { MSE_THROW(msevector_range_error("invalid argument - ss_iterator_type insert_before() - msevector")); } //if (start.m_owner_cptr != end.m_owner_cptr) { MSE_THROW(msevector_range_error("invalid arguments - void insert_before(const ss_const_iterator_type &pos, const ss_const_iterator_type &start, const ss_const_iterator_type &end) - msevector")); } pos.assert_valid_index(); msev_size_t original_pos = pos.position(); typename base_class::const_iterator _P = pos; (*this).insert(_P, start, end); ss_iterator_type retval = ss_begin(); retval.advance(msev_int(original_pos)); return retval; } ss_iterator_type insert_before(const ss_const_iterator_type &pos, const ss_const_iterator_type& start, const ss_const_iterator_type &end) { if (start.m_owner_cptr != end.m_owner_cptr) { MSE_THROW(msevector_range_error("invalid arguments - void insert_before(const ss_const_iterator_type &pos, const ss_const_iterator_type &start, const ss_const_iterator_type &end) - msevector")); } end.assert_valid_index(); if (start > end) { MSE_THROW(msevector_range_error("invalid arguments - void insert_before(const ss_const_iterator_type &pos, const ss_const_iterator_type &start, const ss_const_iterator_type &end) - msevector")); } typename base_class::const_iterator _S = start; typename base_class::const_iterator _E = end; return (*this).insert_before(pos, _S, _E); } ss_iterator_type insert_before(const ss_const_iterator_type &pos, const _Ty* start, const _Ty* end) { if (pos.m_owner_cptr != this) { MSE_THROW(msevector_range_error("invalid arguments - ss_iterator_type insert_before() - msevector")); } //if (start.m_owner_cptr != end.m_owner_cptr) { MSE_THROW(msevector_range_error("invalid arguments - void insert_before(const ss_const_iterator_type &pos, const ss_const_iterator_type &start, const ss_const_iterator_type &end) - msevector")); } if (start > end) { MSE_THROW(msevector_range_error("invalid arguments - ss_iterator_type insert_before() - msevector")); } pos.assert_valid_index(); msev_size_t original_pos = pos.position(); typename base_class::const_iterator _P = pos; (*this).insert(_P, start, end); ss_iterator_type retval = ss_begin(); retval.advance(msev_int(original_pos)); return retval; } templatetypename std::enable_if<_mse_Is_iterator<_Iter>::value, typename base_class::iterator>::type , class = _mse_RequireInputIter<_Iter> > ss_iterator_type insert_before_inclusive(const ss_iterator_type &pos, const _Iter &first, const _Iter &last) { auto end = last; end++; // this may include some checks return (*this).insert_before(pos, first, end); } ss_iterator_type insert_before(const ss_const_iterator_type &pos, _XSTD initializer_list _Ilist) { // insert initializer_list if (pos.m_owner_ptr != this) { MSE_THROW(msevector_range_error("invalid arguments - void insert_before() - msevector")); } pos.assert_valid_index(); msev_size_t original_pos = pos.position(); typename base_class::const_iterator _P = pos; (*this).insert(_P, _Ilist); ss_iterator_type retval = ss_begin(); retval.advance(msev_int(original_pos)); return retval; } /* These insert() functions are just aliases for their corresponding insert_before() functions. */ ss_iterator_type insert(const ss_const_iterator_type &pos, size_type _M, const _Ty& _X) { return insert_before(pos, _M, _X); } ss_iterator_type insert(const ss_const_iterator_type &pos, _Ty&& _X) { return insert_before(pos, std::move(_X)); } ss_iterator_type insert(const ss_const_iterator_type &pos, const _Ty& _X = _Ty()) { return insert_before(pos, _X); } templatetypename std::enable_if<_mse_Is_iterator<_Iter>::value, typename base_class::iterator>::type , class = _mse_RequireInputIter<_Iter> > ss_iterator_type insert(const ss_const_iterator_type &pos, const _Iter &start, const _Iter &end) { return insert_before(pos, start, end); } ss_iterator_type insert(const ss_const_iterator_type &pos, const _Ty* start, const _Ty* &end) { return insert_before(pos, start, end); } ss_iterator_type insert(const ss_const_iterator_type &pos, _XSTD initializer_list _Ilist) { return insert_before(pos, _Ilist); } template #if !(defined(GPP4P8_COMPATIBLE)) ss_iterator_type emplace(const ss_const_iterator_type &pos, _Valty&& ..._Val) { // insert by moving _Val at pos if (pos.m_owner_cptr != this) { MSE_THROW(msevector_range_error("invalid arguments - void emplace() - msevector")); } #else /*!(defined(GPP4P8_COMPATIBLE))*/ ipointer emplace(const ipointer &pos, _Valty&& ..._Val) { // insert by moving _Val at pos if (pos.m_owner_ptr != this) { MSE_THROW(msevector_range_error("invalid arguments - void emplace() - msevector")); } #endif /*!(defined(GPP4P8_COMPATIBLE))*/ pos.assert_valid_index(); msev_size_t original_pos = pos.position(); typename base_class::const_iterator _P = pos; (*this).emplace(_P, std::forward<_Valty>(_Val)...); ss_iterator_type retval = ss_begin(); retval.advance(msev_int(original_pos)); return retval; } ss_iterator_type erase(const ss_const_iterator_type &pos) { if (pos.m_owner_cptr != this) { MSE_THROW(msevector_range_error("invalid arguments - void erase() - msevector")); } if (!pos.points_to_an_item()) { MSE_THROW(msevector_range_error("invalid arguments - void erase() - msevector")); } auto pos_index = pos.position(); typename base_class::const_iterator _P = pos; (*this).erase(_P); ss_iterator_type retval = (*this).ss_begin(); retval.advance(typename ss_const_iterator_type::difference_type(pos_index)); return retval; } ss_iterator_type erase(const ss_const_iterator_type &start, const ss_const_iterator_type &end) { if (start.m_owner_cptr != this) { MSE_THROW(msevector_range_error("invalid arguments - void erase() - msevector")); } if (end.m_owner_cptr != this) { MSE_THROW(msevector_range_error("invalid arguments - void erase() - msevector")); } if (start.position() > end.position()) { MSE_THROW(msevector_range_error("invalid arguments - void erase() - msevector")); } auto pos_index = start.position(); typename base_class::const_iterator _F = start; typename base_class::const_iterator _L = end; (*this).erase(_F, _L); ss_iterator_type retval = (*this).ss_begin(); retval.advance(typename ss_const_iterator_type::difference_type(pos_index)); return retval; } ss_iterator_type erase_inclusive(const ss_const_iterator_type &first, const ss_const_iterator_type &last) { auto end = last; end.set_to_next(); return erase(first, end); } void erase_previous_item(const ss_const_iterator_type &pos) { if (pos.m_owner_cptr != this) { MSE_THROW(msevector_range_error("invalid arguments - void erase_previous_item() - msevector")); } if (!(pos.has_previous())) { MSE_THROW(msevector_range_error("invalid arguments - void erase_previous_item() - msevector")); } typename base_class::const_iterator _P = pos; _P--; (*this).erase(_P); } }; } #undef MSE_THROW #endif /*ndef MSEMSEVECTOR_H*/