Skip to content
Snippets Groups Projects
Commit 5430e3fc authored by Jan Trávníček's avatar Jan Trávníček
Browse files

introduce ptr_vector

parent 6eaeb465
No related branches found
No related tags found
No related merge requests found
#include <extensions/ptr_vector.hpp>
/*
* 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 ) {
m_data.at ( std::distance ( cbegin ( ), pos ) ) = ext::clone ( std::forward < R > ( value ) );
return dereferencer ( m_data.begin ( ) + std::distance ( cbegin ( ), pos ) );
}
template < class R >
iterator set ( const_iterator pos, T * value ) {
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 ) {
m_data.at ( std::distance ( cbegin ( ), pos ) ) = new R ( std::forward < Args > ( args ) ... ) ;
return dereferencer ( m_data.begin ( ) + std::distance ( cbegin ( ), pos ) );
}
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 );
}
};
} /* namespace ext */
namespace std {
template < class ... Ts >
void swap ( ext::ptr_vector < Ts ... > & first, ext::ptr_vector < Ts ... > & second ) {
first.swap ( second );
}
} /* namespace std */
namespace ext {
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_ */
#include "PtrVectorTest.h"
#include <alib/ptr_vector>
#include <alib/algorithm>
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( PtrVectorTest, "bits" );
CPPUNIT_TEST_SUITE_REGISTRATION( PtrVectorTest );
void PtrVectorTest::setUp() {
}
void PtrVectorTest::tearDown() {
}
void PtrVectorTest::testProperties() {
ext::ptr_vector < int > data = {1, 2, 3, 4};
std::cout << data [ 0 ] << std::endl;
CPPUNIT_ASSERT ( data [ 0 ] == 1 );
CPPUNIT_ASSERT ( data.size ( ) == 4 );
CPPUNIT_ASSERT ( data [ 3 ] == 4 );
data.push_back ( 1 );
CPPUNIT_ASSERT ( data.size ( ) == 5 );
CPPUNIT_ASSERT ( data [ 4 ] == 1 );
data.insert ( data.cbegin ( ) + 1, 2 );
CPPUNIT_ASSERT ( data.size ( ) == 6 );
CPPUNIT_ASSERT ( data [ 1 ] == 2 );
CPPUNIT_ASSERT ( data [ 2 ] == 2 );
CPPUNIT_ASSERT ( data [ 3 ] == 3 );
}
void PtrVectorTest::testPolymorph() {
ext::ptr_vector < Base > data = { Child2 ( ) };
CPPUNIT_ASSERT ( data [ 0 ].type ( ) == PtrVectorTest::Type::CHILD2 );
CPPUNIT_ASSERT ( data.size ( ) == 1 );
data.push_back ( Child1 ( ) );
CPPUNIT_ASSERT ( data.size ( ) == 2 );
CPPUNIT_ASSERT ( data [ 1 ].type ( ) == PtrVectorTest::Type::CHILD1 );
ext::ptr_vector < Base >::const_iterator iter = data.cbegin ( );
CPPUNIT_ASSERT ( iter->type ( ) == PtrVectorTest::Type::CHILD2 );
++ iter;
CPPUNIT_ASSERT ( iter->type ( ) == PtrVectorTest::Type::CHILD1 );
++ iter;
CPPUNIT_ASSERT ( iter == data.cend ( ) );
data.insert ( data.cbegin ( ) + 1, Child1 ( ) );
CPPUNIT_ASSERT ( data.size ( ) == 3 );
CPPUNIT_ASSERT ( data [ 0 ].type ( ) == PtrVectorTest::Type::CHILD2 );
CPPUNIT_ASSERT ( data [ 1 ].type ( ) == PtrVectorTest::Type::CHILD1 );
CPPUNIT_ASSERT ( data [ 2 ].type ( ) == PtrVectorTest::Type::CHILD1 );
data.resize ( 4 );
CPPUNIT_ASSERT ( data.null ( 3 ) );
data.resize ( 3 );
ext::ptr_vector < Base > data2 = data;
CPPUNIT_ASSERT ( data2 [ 0 ].type ( ) == PtrVectorTest::Type::CHILD2 );
CPPUNIT_ASSERT ( data2 [ 1 ].type ( ) == PtrVectorTest::Type::CHILD1 );
CPPUNIT_ASSERT ( data2 [ 2 ].type ( ) == PtrVectorTest::Type::CHILD1 );
auto iter2 = data2.insert ( data2.cbegin ( ) + 1, data.begin ( ), data.end ( ) );
CPPUNIT_ASSERT ( iter2 == data2.begin ( ) + 1 );
CPPUNIT_ASSERT ( data2 [ 0 ].type ( ) == PtrVectorTest::Type::CHILD2 );
CPPUNIT_ASSERT ( data2 [ 1 ].type ( ) == PtrVectorTest::Type::CHILD2 );
CPPUNIT_ASSERT ( data2 [ 2 ].type ( ) == PtrVectorTest::Type::CHILD1 );
CPPUNIT_ASSERT ( data2 [ 3 ].type ( ) == PtrVectorTest::Type::CHILD1 );
CPPUNIT_ASSERT ( data2 [ 4 ].type ( ) == PtrVectorTest::Type::CHILD1 );
CPPUNIT_ASSERT ( data2 [ 5 ].type ( ) == PtrVectorTest::Type::CHILD1 );
data2.erase ( ext::dereferencer ( ext::unique ( data2.begin ( ).base ( ), data2.end ( ).base ( ), [ ] ( const Base * a, const Base * b ) { return * a == * b; } ) ), data2.end ( ) );
}
#ifndef PTR_VECTOR_TEST_H_
#define PTR_VECTOR_TEST_H_
#include <cppunit/extensions/HelperMacros.h>
#include <alib/compare>
class PtrVectorTest : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE( PtrVectorTest );
CPPUNIT_TEST( testProperties );
CPPUNIT_TEST( testPolymorph );
CPPUNIT_TEST_SUITE_END();
enum class Type {
CHILD1,
CHILD2
};
class Base {
public:
virtual ~Base ( ) {
}
virtual Base * clone ( ) const = 0;
virtual Base * plunder ( ) && = 0;
virtual Type type ( ) const = 0;
bool operator == ( const PtrVectorTest::Base & other ) const {
return this->type ( ) == other.type ( );
}
};
class Child1 : public Base {
public:
virtual Base * clone ( ) const {
return new Child1 ( * this );
}
virtual Base * plunder ( ) && {
return new Child1 ( * this );
}
virtual Type type ( ) const {
return Type::CHILD1;
}
};
class Child2 : public Base {
public:
virtual Base * clone ( ) const {
return new Child2 ( * this );
}
virtual Base * plunder ( ) && {
return new Child2 ( * this );
}
virtual Type type ( ) const {
return Type::CHILD2;
}
};
public:
void setUp();
void tearDown();
void testProperties();
void testPolymorph();
};
#endif // PTR_VECTOR_TEST_H_
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment