/* * ptr_vector.hpp * * Created on: Feb 28, 2014 * Author: Jan Travnicek */ #ifndef __PTR_VECTOR_HPP_ #define __PTR_VECTOR_HPP_ #include <vector> #include <ostream> #include <sstream> #include <string> #include "compare.hpp" #include "allocFix.hpp" #include "iterator.hpp" #include "clone.hpp" namespace ext { template < class T > class ptr_vector { std::vector < T * > m_data; public: using value_type = T; using size_type = std::size_t; using diference_type = std::ptrdiff_t; using reference = value_type &; using const_reference = const value_type &; using pointer = T *; using const_pointer = T * const; using iterator = dereferencing_iterator < typename std::vector < T * >::iterator >; using const_iterator = dereferencing_iterator < typename std::vector < T * >::const_iterator >; using reverse_iterator = dereferencing_iterator < typename std::vector < T * >::reverse_iterator >; using const_reverse_iterator = dereferencing_iterator < typename std::vector < T * >::const_reverse_iterator >; ptr_vector ( ) noexcept { } template < class R > ptr_vector ( std::initializer_list < R > init ) { insert ( cbegin ( ), std::move ( init ) ); } ptr_vector ( std::initializer_list < T * > init ) : m_data ( init ) { } explicit ptr_vector ( size_type count ) { resize ( count ); } template < class InputIt > ptr_vector ( InputIt first, InputIt last ) { insert ( cbegin ( ), first, last ); } ptr_vector ( size_type count, const T& value ) { insert ( cbegin ( ), count, value ); } ptr_vector ( const ptr_vector& other ) { insert ( cbegin ( ), other.begin ( ), other.end ( ) ); } ptr_vector ( ptr_vector && other ) noexcept { std::swap ( m_data, other.m_data ); } ~ptr_vector ( ) noexcept { clear ( ); } ptr_vector < T > & operator = ( const ptr_vector < T > & other ) { if ( this == & other ) return * this; clear ( ); insert ( cbegin ( ), other.begin ( ), other.end ( ) ); return *this; } ptr_vector < T > & operator = ( ptr_vector < T > && other ) noexcept { std::swap ( m_data, other.m_data ); return *this; } void assign ( size_type count, const T& value ) { clear ( ); insert ( cbegin ( ), count, value ); } template< class InputIt > void assign ( InputIt first, InputIt last ) { clear ( ); insert ( cbegin ( ), first, last ); } template < class R > void assign ( std::initializer_list < R > ilist ) { clear ( ); insert ( cbegin ( ), std::move ( ilist ) ); } reference at ( size_type index ) { return * m_data.at ( index ); } const_reference at ( size_type index ) const { return * m_data.at ( index ); } reference operator [ ] ( size_type index ) { return * m_data [ index ]; } const_reference operator [ ] ( size_type index ) const { return * m_data [ index ]; } reference front ( ) { return * m_data.front ( ); } const_reference front ( ) const { return * m_data.front ( ); } reference back ( ) { return * m_data.back ( ); } const_reference back ( ) const { return * m_data.back ( ); } bool null ( size_type index ) const { return m_data.at ( index ) == NULL; } /* T * const * data ( ) noexcept { return m_data.data ( ); } T const * const * data ( ) const noexcept { return m_data.data ( ); } */ iterator begin ( ) noexcept { return dereferencer ( m_data.begin ( ) ); } const_iterator begin ( ) const noexcept { return dereferencer ( m_data.begin ( ) ); } const_iterator cbegin ( ) const noexcept { return dereferencer ( m_data.cbegin ( ) ); } iterator end ( ) noexcept { return dereferencer ( m_data.end ( ) ); } const_iterator end ( ) const noexcept { return dereferencer ( m_data.end ( ) ); } const_iterator cend ( ) const noexcept { return dereferencer ( m_data.cend ( ) ); } reverse_iterator rbegin ( ) noexcept { return dereferencer ( m_data.rbegin ( ) ); } const_reverse_iterator rbegin ( ) const noexcept { return dereferencer ( m_data.rbegin ( ) ); } const_reverse_iterator crbegin ( ) const noexcept { return dereferencer ( m_data.crbegin ( ) ); } reverse_iterator rend ( ) noexcept { return dereferencer ( m_data.rend ( ) ); } const_reverse_iterator rend ( ) const noexcept { return dereferencer ( m_data.rend ( ) ); } const_reverse_iterator crend ( ) const noexcept { return dereferencer ( m_data.crend ( ) ); } bool empty ( ) const noexcept { return m_data.empty ( ); } size_type size ( ) const noexcept { return m_data.size ( ); } size_type max_size ( ) const noexcept { return m_data.max_size ( ); } void reserve ( size_type new_cap ) { m_data.reserve ( new_cap ); } size_type capacity ( ) const noexcept { return m_data.capacity ( ); } void shrink_to_fit ( ) { m_data.shrink_to_fit ( ); } void clear ( ) noexcept { for ( T * data : m_data ) { delete data; } m_data.clear ( ); } template < class R > iterator set ( const_iterator pos, R && value ) { return set ( pos, ext::clone ( std::forward < R > ( value ) ) ); } iterator set ( const_iterator pos, T * value ) { delete m_data.at ( std::distance ( cbegin ( ), pos ) ); m_data.at ( std::distance ( cbegin ( ), pos ) ) = value; return dereferencer ( m_data.begin ( ) + std::distance ( cbegin ( ), pos ) ); } template < class R, class ... Args > iterator emplace_set ( const_iterator pos, Args && ... args ) { return set ( pos, new R ( std::forward < R > ( args ) ... ) ); } template < class R > iterator insert ( const_iterator pos, R && value ) { return dereferencer ( m_data.insert ( pos.base ( ), ext::clone ( std::forward < R > ( value ) ) ) ); } template < class R > iterator insert ( const_iterator pos, size_type count, const R & value ) { iterator res = dereferencer ( m_data.insert ( pos.base ( ), count, NULL ) ); for ( size_type i = 0; i < count; ++ i ) { * ( res.base ( ) + i ) = ext::clone ( value ); } return res; } template < class InputIt > iterator insert ( const_iterator pos, InputIt first, InputIt last ) { size_type size = std::distance ( first, last ); iterator res = dereferencer ( m_data.insert ( pos.base ( ), size, NULL ) ); for ( size_type i = 0; i < size; ++ first, ++ i ) * ( res.base ( ) + i ) = ext::clone ( * first ); return res; } template < class R > iterator insert ( const_iterator pos, std::initializer_list < R > ilist ) { return insert ( pos, ilist.begin ( ), ilist.end ( ) ); } template < class R > iterator insert ( const_iterator pos, T * value ) { return m_data.insert ( pos.base ( ), value ); } template < class R, class ... Args > iterator emplace ( const_iterator pos, Args && ... args ) { return dereferencer ( m_data.insert ( pos.base ( ), new R ( std::forward < Args > ( args ) ... ) ) ); } iterator erase ( const_iterator pos ) { delete * pos.base ( ); return dereferencer ( m_data.erase ( pos.base ( ) ) ); } iterator erase ( const_iterator first, const_iterator last ) { for ( const_iterator first_copy = first; first_copy != last; ++ first_copy ) { delete * first_copy.base ( ); } return dereferencer ( m_data.erase ( first.base ( ), last.base ( ) ) ); } template < class R > void push_back ( R && value ) { insert ( cend ( ), std::forward < R > ( value ) ); } template < class ... Args > reference emplace_back ( Args && ... args ) { return * emplace ( cend ( ), std::forward < Args > ( args ) ... ); } void pop_back ( ) { T * value = m_data.back ( ); delete value; m_data.pop_back ( ); } void resize ( size_type count ) { for ( size_type i = count; i < m_data.size ( ); ++ i ) { delete m_data [ i ]; } size_type i = m_data.size ( ); m_data.resize ( count ); for ( ; i < count; ++ i ) { m_data [ i ] = NULL; } } template < class R > void resize ( size_type count, const R & value ) { for ( size_type i = count; i < m_data.size ( ); ++ i ) { delete m_data [ i ]; } size_type i = m_data.size ( ); m_data.resize ( count ); for ( ; i < count; ++ i ) { m_data [ i ] = ext::clone ( value ); } } void swap ( ptr_vector & other ) { std::swap ( this->m_data, other.m_data ); } }; template< class T > std::ostream& operator<<(std::ostream& out, const ext::ptr_vector < T > & ptr_vector) { out << "["; bool first = true; for(const T& item : ptr_vector) { if(!first) out << ", "; first = false; out << item; } out << "]"; return out; } template<class T > struct compare < ext::ptr_vector < T > > { int operator()(const ext::ptr_vector < T >& first, const ext::ptr_vector < T > & second) const { if(first.size() < second.size()) return -1; if(first.size() > second.size()) return 1; static compare<typename std::decay < T >::type > comp; for(auto iterF = first.begin(), iterS = second.begin(); iterF != first.end(); ++iterF, ++iterS) { int res = comp(*iterF, *iterS); if(res != 0) return res; } return 0; } }; template < class T > std::string to_string ( const ext::ptr_vector < T > & value ) { std::stringstream ss; ss << value; return ss.str(); } template < class T > bool operator == ( const ptr_vector < T > & first, const ptr_vector < T > & second ) { static compare < ptr_vector < T > > comp; return comp ( first, second ) == 0; } template < class T > bool operator != ( const ptr_vector < T > & first, const ptr_vector < T > & second ) { return ! ( first == second ); } template < class T > bool operator < ( const ptr_vector < T > & first, const ptr_vector < T > & second ) { static compare < ptr_vector < T > > comp; return comp ( first, second ) < 0; } template < class T > bool operator > ( const ptr_vector < T > & first, const ptr_vector < T > & second ) { return second < first; } template < class T > bool operator <= ( const ptr_vector < T > & first, const ptr_vector < T > & second ) { return ! ( first > second ); } template < class T > bool operator >= ( const ptr_vector < T > & first, const ptr_vector < T > & second ) { return ! ( first < second ); } } /* namespace ext */ #endif /* __PTR_VECTOR_HPP_ */