글수 49
크기가 고정되어있는 1차원 배열 컨테이너입니다.
일반 배열과 차이점은
따로 크기를 알 필요가 없고
범위를 벗어나는곳에 접근하는걸 막을 수 있으며
복사가 가능하고
STL 알고리즘 적용이 쉽다는 점입니다.
vector를 참고해서 만들었고, 크기가 고정되어 있으므로 인스턴스 생성시 크기를 지정해줘야하며 삽입, 삭제같은 기능은 안됩니다. resize는 가능합니다.
크기가 다른 배열끼리 swap이나 대입역시 안됩니다. 단 copy로는 가능합니다.
범위를 벗어나는곳에 접근하면 assertion fail이 납니다.
reverse_iterator는 안만들었습니다.
버그,수정할 부분,개선되야할점은 알려주세요 꼭.
STL 알고리즘, 컨테이너와 호환됩니다.
(단 크기가 고정되어 있으므로 STL 컨테이너에서 삽입은 불가능.)
구현물:
[code]#include <iostream>
#include <iterator>
#include <algorithm>
#include <numeric>
#include <map>
#include <vector>
#include <list>
#include <cassert>
using namespace std;
// enable this definition if you want 'out of range' test in array1 class
#define ARRAY1_TEST_OUT_OF_RANGE
template <typename Type>
class array1
{
public:
typedef unsigned int size_type;
typedef Type value_type;
typedef unsigned int difference_type;
typedef Type * pointer;
typedef Type & reference;
typedef const Type * const_pointer;
typedef const Type & const_reference;
class const_iterator
{
protected:
pointer m_ptr;
public:
typedef unsigned int difference_type;
typedef Type value_type;
typedef difference_type difference;
typedef value_type value;
typedef value* pointer;
typedef value& reference;
// typedef iterator;
typedef random_access_iterator_tag iterator_category;
const_iterator()
{
m_ptr = 0;
}
const_iterator(pointer ptr)
{
m_ptr = ptr;
}
const_reference operator*() const
{
return (*m_ptr);
}
pointer operator->() const
{ // return pointer to class object
return (&**this);
}
const_iterator& operator++()
{ // preincrement
++m_ptr;
return (*this);
}
const_iterator operator++(int)
{ // postincrement
const_iterator _Tmp = *this;
++*this;
return (_Tmp);
}
const_iterator& operator--()
{ // predecrement
--m_ptr;
return (*this);
}
const_iterator operator--(int)
{ // postdecrement
const_iterator _Tmp = *this;
--*this;
return (_Tmp);
}
const_iterator& operator+=(difference_type _Off)
{ // increment by integer
m_ptr += _Off;
return (*this);
}
const_iterator operator+(difference_type _Off) const
{ // return this + integer
const_iterator _Tmp = *this;
return (_Tmp += _Off);
}
const_iterator& operator-=(difference_type _Off)
{ // decrement by integer
return (*this += -_Off);
}
const_iterator operator-(difference_type _Off) const
{ // return this - integer
const_iterator _Tmp = *this;
return (_Tmp -= _Off);
}
difference_type operator-(const const_iterator& _Right) const
{ // return difference of iterators
return (m_ptr - _Right.m_ptr);
}
const_reference operator[](difference_type _Off) const
{ // subscript
return (*(*this + _Off));
}
bool operator==(const const_iterator& _Right) const
{ // test for iterator equality
return (m_ptr == _Right.m_ptr);
}
bool operator!=(const const_iterator& _Right) const
{ // test for iterator inequality
return (!(*this == _Right));
}
bool operator<(const const_iterator& _Right) const
{ // test if this < _Right
return (m_ptr < _Right.m_ptr);
}
bool operator>(const const_iterator& _Right) const
{ // test if this > _Right
return (_Right < *this);
}
bool operator<=(const const_iterator& _Right) const
{ // test if this <= _Right
return (!(_Right < *this));
}
bool operator>=(const const_iterator& _Right) const
{ // test if this >= _Right
return (!(*this < _Right));
}
friend const_iterator operator+(difference_type _Off,
const const_iterator& _Right)
{ // return iterator + integer
return (_Right + _Off);
}
};
class iterator : public const_iterator
{
public:
iterator()
{ // construct with null vector pointer
}
iterator(pointer _Ptr) : const_iterator(_Ptr)
{ // construct with pointer _Ptr
}
reference operator*() const
{ // return designated object
return ((reference)**(const_iterator *)this);
}
pointer operator->() const
{ // return pointer to class object
return (&**this);
}
iterator& operator++()
{ // preincrement
++this->m_ptr;
return (*this);
}
iterator operator++(int)
{ // postincrement
iterator _Tmp = *this;
++*this;
return (_Tmp);
}
iterator& operator--()
{ // predecrement
--this->m_ptr;
return (*this);
}
iterator operator--(int)
{ // postdecrement
iterator _Tmp = *this;
--*this;
return (_Tmp);
}
iterator& operator+=(difference_type _Off)
{ // increment by integer
this->m_ptr += _Off;
return (*this);
}
iterator operator+(difference_type _Off) const
{ // return this + integer
iterator _Tmp = *this;
return (_Tmp += _Off);
}
iterator& operator-=(difference_type _Off)
{ // decrement by integer
return (*this += -_Off);
}
iterator operator-(difference_type _Off) const
{ // return this - integer
iterator _Tmp = *this;
return (_Tmp -= _Off);
}
difference_type operator-(const const_iterator& _Right) const
{ // return difference of iterators
return ((const_iterator)*this - _Right);
}
reference operator[](difference_type _Off) const
{ // subscript
return (*(*this + _Off));
}
friend iterator operator+(difference_type _Off, const iterator& _Right)
{ // return iterator + integer
return (_Right + _Off);
}
};
private:
value_type *m_begin, *m_end;
size_type m_size;
public:
array1(size_type size = 0, const value_type &val = Type())
{
m_begin = 0;
m_end = 0;
m_size = 0;
assign(size, val);
}
~array1()
{
clear();
}
void assign(size_type size, const value_type &val)
{
clear();
m_size = size;
m_begin = new value_type[m_size];
m_end = &m_begin[size];
for(size_type i = 0; i < m_size; i++)
{
m_begin[i] = val;
}
}
bool test_in_range(size_type pos) const
{
bool in_range = (0 <= pos && pos < size());
assert(in_range && "array1 position is out of range");
return in_range;
}
reference at(size_type pos)
{
#ifdef ARRAY1_TEST_OUT_OF_RANGE
test_in_range(pos);
#endif
return m_begin[pos];
}
const_reference at(size_type pos) const
{
#ifdef ARRAY1_TEST_OUT_OF_RANGE
test_in_range(pos);
#endif
return m_begin[pos];
}
iterator begin()
{
return m_begin;
}
const_iterator begin() const
{
return m_begin;
}
iterator end()
{
return m_end;
}
const_iterator end() const
{
return m_end;
}
void clear()
{
delete []m_begin;
m_begin = 0;
m_end = 0;
m_size = 0;
}
bool empty() const
{
return !m_size;
}
/*
reverse_iterator rbegin()
{
}
reverse_iterator rend()
{
}
*/
void resize(size_type newsize)
{
assign(newsize, value_type());
}
size_type size() const
{
return m_size;
}
bool same_size(const array1 &rhs)
{
return size() == rhs.size();
}
bool swap(array1 &rhs)
{
if(same_size(rhs))
{
swap(*this, rhs);
return true;
}
return false;
}
friend void swap(array1 &lhs, array1 &rhs);
bool operator=(const array1 &rhs)
{
if(same_size(rhs))
{
copy(rhs);
return true;
}
return false;
}
void copy(const array1 &rhs)
{
// realloc
assign(rhs.size(), value_type());
// copy
for(size_type i = 0; i < size(); i++)
{
at(i) = rhs.at(i);
}
}
reference operator[](size_type pos)
{
return at(pos);
}
const_reference operator[](size_type pos) const
{
return at(pos);
}
};
template <typename Type>
bool swap(array1<Type> &lhs, array1<Type> &rhs)
{
if(lhs.same_size(rhs))
{
array1 buf = lhs;
lhs = rhs;
rhs = buf;
return true;
}
return false;
}
[/code]
테스트 코드:
[code]template <typename ContainerTy>
void enumElems(const ContainerTy &ty)
{
for(ContainerTy::const_iterator i = ty.begin(); i != ty.end(); i++)
{
cout << *i << endl;
}
}
int main()
{
typedef array1<int> testar;
typedef list<int> testlst;
testar ar(3, 1), ar2(4), ar3(5);
cout << "ar: " << endl;
enumElems(ar);
// accessor
ar[0] = 1;
ar[1] = 2;
ar[2] = 3;
cout << "enumerate elems: " << endl;
enumElems(ar);
// apply STL algorithm
int sum = accumulate(ar.begin(), ar.end(), 0);
cout << "sum of all elems : " << sum << endl;
// reallocate
ar.resize(4);
cout << "array resized" << endl;
for(testar::iterator i = ar.begin(); i != ar.end(); i++)
{
*i = i - ar.begin() + 1;
}
cout << "enumulate elems again" << endl;
enumElems(ar);
// iterator
testar::iterator beg = ar.begin();
beg++;
cout << "second elem: " << *beg << endl;
// copy
cout << "enum ar2: " << endl;
ar2 = ar;
enumElems(ar2);
cout << "enum ar3 " << endl;
ar3 = ar;
enumElems(ar3);
// compatability with another container
testlst lst;
lst.insert(lst.begin(), ar.begin(), ar.end());
cout << "enum list elems: " << endl;
enumElems(lst);
// 'out of range' test. it occurs 'assertion failed' error
ar[-1];
return 0;
}
[/code]
일반 배열과 차이점은
따로 크기를 알 필요가 없고
범위를 벗어나는곳에 접근하는걸 막을 수 있으며
복사가 가능하고
STL 알고리즘 적용이 쉽다는 점입니다.
vector를 참고해서 만들었고, 크기가 고정되어 있으므로 인스턴스 생성시 크기를 지정해줘야하며 삽입, 삭제같은 기능은 안됩니다. resize는 가능합니다.
크기가 다른 배열끼리 swap이나 대입역시 안됩니다. 단 copy로는 가능합니다.
범위를 벗어나는곳에 접근하면 assertion fail이 납니다.
reverse_iterator는 안만들었습니다.
버그,수정할 부분,개선되야할점은 알려주세요 꼭.
STL 알고리즘, 컨테이너와 호환됩니다.
(단 크기가 고정되어 있으므로 STL 컨테이너에서 삽입은 불가능.)
구현물:
[code]#include <iostream>
#include <iterator>
#include <algorithm>
#include <numeric>
#include <map>
#include <vector>
#include <list>
#include <cassert>
using namespace std;
// enable this definition if you want 'out of range' test in array1 class
#define ARRAY1_TEST_OUT_OF_RANGE
template <typename Type>
class array1
{
public:
typedef unsigned int size_type;
typedef Type value_type;
typedef unsigned int difference_type;
typedef Type * pointer;
typedef Type & reference;
typedef const Type * const_pointer;
typedef const Type & const_reference;
class const_iterator
{
protected:
pointer m_ptr;
public:
typedef unsigned int difference_type;
typedef Type value_type;
typedef difference_type difference;
typedef value_type value;
typedef value* pointer;
typedef value& reference;
// typedef iterator;
typedef random_access_iterator_tag iterator_category;
const_iterator()
{
m_ptr = 0;
}
const_iterator(pointer ptr)
{
m_ptr = ptr;
}
const_reference operator*() const
{
return (*m_ptr);
}
pointer operator->() const
{ // return pointer to class object
return (&**this);
}
const_iterator& operator++()
{ // preincrement
++m_ptr;
return (*this);
}
const_iterator operator++(int)
{ // postincrement
const_iterator _Tmp = *this;
++*this;
return (_Tmp);
}
const_iterator& operator--()
{ // predecrement
--m_ptr;
return (*this);
}
const_iterator operator--(int)
{ // postdecrement
const_iterator _Tmp = *this;
--*this;
return (_Tmp);
}
const_iterator& operator+=(difference_type _Off)
{ // increment by integer
m_ptr += _Off;
return (*this);
}
const_iterator operator+(difference_type _Off) const
{ // return this + integer
const_iterator _Tmp = *this;
return (_Tmp += _Off);
}
const_iterator& operator-=(difference_type _Off)
{ // decrement by integer
return (*this += -_Off);
}
const_iterator operator-(difference_type _Off) const
{ // return this - integer
const_iterator _Tmp = *this;
return (_Tmp -= _Off);
}
difference_type operator-(const const_iterator& _Right) const
{ // return difference of iterators
return (m_ptr - _Right.m_ptr);
}
const_reference operator[](difference_type _Off) const
{ // subscript
return (*(*this + _Off));
}
bool operator==(const const_iterator& _Right) const
{ // test for iterator equality
return (m_ptr == _Right.m_ptr);
}
bool operator!=(const const_iterator& _Right) const
{ // test for iterator inequality
return (!(*this == _Right));
}
bool operator<(const const_iterator& _Right) const
{ // test if this < _Right
return (m_ptr < _Right.m_ptr);
}
bool operator>(const const_iterator& _Right) const
{ // test if this > _Right
return (_Right < *this);
}
bool operator<=(const const_iterator& _Right) const
{ // test if this <= _Right
return (!(_Right < *this));
}
bool operator>=(const const_iterator& _Right) const
{ // test if this >= _Right
return (!(*this < _Right));
}
friend const_iterator operator+(difference_type _Off,
const const_iterator& _Right)
{ // return iterator + integer
return (_Right + _Off);
}
};
class iterator : public const_iterator
{
public:
iterator()
{ // construct with null vector pointer
}
iterator(pointer _Ptr) : const_iterator(_Ptr)
{ // construct with pointer _Ptr
}
reference operator*() const
{ // return designated object
return ((reference)**(const_iterator *)this);
}
pointer operator->() const
{ // return pointer to class object
return (&**this);
}
iterator& operator++()
{ // preincrement
++this->m_ptr;
return (*this);
}
iterator operator++(int)
{ // postincrement
iterator _Tmp = *this;
++*this;
return (_Tmp);
}
iterator& operator--()
{ // predecrement
--this->m_ptr;
return (*this);
}
iterator operator--(int)
{ // postdecrement
iterator _Tmp = *this;
--*this;
return (_Tmp);
}
iterator& operator+=(difference_type _Off)
{ // increment by integer
this->m_ptr += _Off;
return (*this);
}
iterator operator+(difference_type _Off) const
{ // return this + integer
iterator _Tmp = *this;
return (_Tmp += _Off);
}
iterator& operator-=(difference_type _Off)
{ // decrement by integer
return (*this += -_Off);
}
iterator operator-(difference_type _Off) const
{ // return this - integer
iterator _Tmp = *this;
return (_Tmp -= _Off);
}
difference_type operator-(const const_iterator& _Right) const
{ // return difference of iterators
return ((const_iterator)*this - _Right);
}
reference operator[](difference_type _Off) const
{ // subscript
return (*(*this + _Off));
}
friend iterator operator+(difference_type _Off, const iterator& _Right)
{ // return iterator + integer
return (_Right + _Off);
}
};
private:
value_type *m_begin, *m_end;
size_type m_size;
public:
array1(size_type size = 0, const value_type &val = Type())
{
m_begin = 0;
m_end = 0;
m_size = 0;
assign(size, val);
}
~array1()
{
clear();
}
void assign(size_type size, const value_type &val)
{
clear();
m_size = size;
m_begin = new value_type[m_size];
m_end = &m_begin[size];
for(size_type i = 0; i < m_size; i++)
{
m_begin[i] = val;
}
}
bool test_in_range(size_type pos) const
{
bool in_range = (0 <= pos && pos < size());
assert(in_range && "array1 position is out of range");
return in_range;
}
reference at(size_type pos)
{
#ifdef ARRAY1_TEST_OUT_OF_RANGE
test_in_range(pos);
#endif
return m_begin[pos];
}
const_reference at(size_type pos) const
{
#ifdef ARRAY1_TEST_OUT_OF_RANGE
test_in_range(pos);
#endif
return m_begin[pos];
}
iterator begin()
{
return m_begin;
}
const_iterator begin() const
{
return m_begin;
}
iterator end()
{
return m_end;
}
const_iterator end() const
{
return m_end;
}
void clear()
{
delete []m_begin;
m_begin = 0;
m_end = 0;
m_size = 0;
}
bool empty() const
{
return !m_size;
}
/*
reverse_iterator rbegin()
{
}
reverse_iterator rend()
{
}
*/
void resize(size_type newsize)
{
assign(newsize, value_type());
}
size_type size() const
{
return m_size;
}
bool same_size(const array1 &rhs)
{
return size() == rhs.size();
}
bool swap(array1 &rhs)
{
if(same_size(rhs))
{
swap(*this, rhs);
return true;
}
return false;
}
friend void swap(array1 &lhs, array1 &rhs);
bool operator=(const array1 &rhs)
{
if(same_size(rhs))
{
copy(rhs);
return true;
}
return false;
}
void copy(const array1 &rhs)
{
// realloc
assign(rhs.size(), value_type());
// copy
for(size_type i = 0; i < size(); i++)
{
at(i) = rhs.at(i);
}
}
reference operator[](size_type pos)
{
return at(pos);
}
const_reference operator[](size_type pos) const
{
return at(pos);
}
};
template <typename Type>
bool swap(array1<Type> &lhs, array1<Type> &rhs)
{
if(lhs.same_size(rhs))
{
array1 buf = lhs;
lhs = rhs;
rhs = buf;
return true;
}
return false;
}
[/code]
테스트 코드:
[code]template <typename ContainerTy>
void enumElems(const ContainerTy &ty)
{
for(ContainerTy::const_iterator i = ty.begin(); i != ty.end(); i++)
{
cout << *i << endl;
}
}
int main()
{
typedef array1<int> testar;
typedef list<int> testlst;
testar ar(3, 1), ar2(4), ar3(5);
cout << "ar: " << endl;
enumElems(ar);
// accessor
ar[0] = 1;
ar[1] = 2;
ar[2] = 3;
cout << "enumerate elems: " << endl;
enumElems(ar);
// apply STL algorithm
int sum = accumulate(ar.begin(), ar.end(), 0);
cout << "sum of all elems : " << sum << endl;
// reallocate
ar.resize(4);
cout << "array resized" << endl;
for(testar::iterator i = ar.begin(); i != ar.end(); i++)
{
*i = i - ar.begin() + 1;
}
cout << "enumulate elems again" << endl;
enumElems(ar);
// iterator
testar::iterator beg = ar.begin();
beg++;
cout << "second elem: " << *beg << endl;
// copy
cout << "enum ar2: " << endl;
ar2 = ar;
enumElems(ar2);
cout << "enum ar3 " << endl;
ar3 = ar;
enumElems(ar3);
// compatability with another container
testlst lst;
lst.insert(lst.begin(), ar.begin(), ar.end());
cout << "enum list elems: " << endl;
enumElems(lst);
// 'out of range' test. it occurs 'assertion failed' error
ar[-1];
return 0;
}
[/code]
blog: http://ljh131.tistory.com
email: ljh131@gmail.com
