강좌를 너무 안써서 근질근질한지라 몸풀기 취지로 예제를 작성했다.
다음은 가장 기본적인 iterator 형태다.
++ != * 오퍼레이터랑 begin end 함수를 구현해주면 된다.
template< class type, uu array_size >
class vector_array
{
public:
using series_type = std::array< std::vector< type >, array_size >;
using iter_type = typename std::vector< type >::iterator;
series_type series;
CRE vector_array() = default;
class iterator
{
series_type& series;
iter_type it;
uu index;
public:
CRE iterator( series_type& series, uu index, iter_type it )
: series( series )
, index( index )
, it( it )
{}
iterator& operator++()
{
++it;
while( it == series[ index ].end() && ++index < array_size )
it = series[ index ].begin();
return *this;
}
bool operator!=( iterator& other ) const
{
return it._Ptr != other.it._Ptr;
}
auto operator*() const
{
return *it;
}
};
iterator begin()
{
for( uu i = 0; i < series.size(); ++i )
if( series[ i ].size() )
return iterator( series, i, series[ i ].begin() );
return end();
}
iterator end()
{
return iterator( series, array_size - 1, series[ array_size - 1 ].end() );
}
auto add( const uu index, const type& item )
{
series[ index ].emplace_back( item );
}
};
위 클래스는 고유 이터레이터를 가진 복합 컨테이너다.
딱히 별거 없긴해도 좀 독특한 기능을 가지고 있다.
여러 vector 중 어느 vector 에 삽입할지 결정할 수 있다는거다. ( add 함수의 index 파라메터로 )
그리고 생성시점에서 지정한 개수만큼 분리 수용된 여러개의 벡터를 한 번에 이터레이션 한다.
예를 들어
vector_array< int, 2 > even_and_odds; 이렇게 두 개를 생성시켜서
even_and_odds.add( 0, rand() * 2 );
even_and_odds.add( 1, rand() * 2 + 1 );
같은 분리수용이 가능하다는거지.
그리곤
for( auto num : even_and_odds )
cout << num << endl;
처럼 두 개의 ( 몇 개든 ) 벡터를 한 번에 이터레이션 한다는게 특징.
STL 이 주는 많은 편의성은 이터레이터들이 부지런히 움직여 주어 만들어진 결과라고 봐도 무방하다.
이터레이터의 구조를 알면 STL 반은 이해한거지.
시작한 김에 저걸 활용해서 조금만 더 편해져 보자.
even / odd 든, 이런식의 category 는 어쨌든 enum 형 선언과 연결될 가능성이 크다.
그러니까 적절한 enum 타입을 주면 적절히 분리수용해주면 좋겠다.
template< class enum_type >
rigid int val( enum_type e )
{
return static_cast< int >( e );
}
enum class 캐스팅이 귀찮아 준비했다.
template< class type, class enum_type >
class vector_enum : public vector_array< type, val( enum_type::count ) >
{
public:
using inherited = vector_array< type, val( enum_type::count ) >;
CRE vector_enum() = default;
auto add( const enum_type index, const type& item )
{
inherited::add( val( index ), item );
}
};
음 날로 먹은 감이 없지 않다. inherited 에 사용된 표현이 두 번 나오는게 눈에 거슬리지만...
다음엔 이 코드를 활용해 배치 방식별로 위치에 따라 정렬되는 박스 클래스를 만들어봐야겠다.
RandomIterator 형태로 조금 수정해야 할 듯.
방금 짜서 올린거라 좀 버그가 있을 수 있습니다.
첫댓글 참. 마지막 클래스의 enum_type::count 를 이야기 하는걸 까먹었다. 여기 주어질 enum 타입은 0부터 시작하는 단순증가형이어야하고 마지막 항목이 count 여야 한단 뜻이다 : ) 복잡한 enum 을 사용하고 싶으면 예전에 올린 enum 패키지를 이용해 각자 좀 수정하도록 하자.