늙어도 심심삼아 코딩 할 수 있도록 소시적 배운 C++의 기억을 회복할 겸 C++ STL deque을 써서 static queue를 만들어 보았다. 임의의 data structure에 대한 pointer 들을 저장하되 정해진 용량까지만 저장한다. Queue size는 가변적이다. enqueue를 시작하면 정해진 용량까지만 채워지고 그 용량을 넘어서면 과거 데이터부터 자동 삭제된다. 또, dequeue할 때마다 size는 하나씩 감소한다. 즉, size는 0 ~ capacity 내에서 유동적이다.
실제 이 static queue를 써먹을 것인지는 중요하지 않다. 여기서는 C++ Class Constructor 기본 개념과 pointer에 대해 빨리 적응하고, 덤으로 C++11에 추가된 move constructor 등에 대해서도 알아 보는데 의의가 있다.
#include <iostream>
#include <deque>
template<typename _Tp>
class StaticQueue
{
public:
typedef typename std::deque<_Tp*> _Tp_Data;
typedef typename _Tp_Data::iterator iterator;
typedef typename _Tp_Data::const_iterator const_iterator;
// default constructor
explicit StaticQueue(size_t capa=100) :
m_size(0), m_capacity(capa)
{
m_dequeue_item = new _Tp;
m_data = new _Tp_Data;
}
// destructor
~StaticQueue() { destroy(); }
// copy constructor
StaticQueue(const StaticQueue& rhs) { copyFrom(rhs); }
// copy assignment operator
StaticQueue& operator=(const StaticQueue& rhs)
{
if(this!=&rhs) {
destroy();
copyFrom(rhs);
}
return *this;
}
#if __cplusplus >= 201103L
// move constructor: -std=c++11
StaticQueue(StaticQueue&& rhs) { moveFrom(rhs); }
// move assignment operator: -std=c++11
StaticQueue& operator=(StaticQueue&& rhs)
{
if(this!=&rhs) {
destroy();
moveFrom(rhs);
}
return *this;
}
#endif
// index operator
const _Tp& operator[](size_t index) const { return *m_data->at(index); }
_Tp& operator[](size_t index) { return *m_data->at(index); }
// getters
size_t size() const { return m_size; }
size_t capacity() const { return m_capacity; }
_Tp_Data* data() const { return m_data; }
// setters
void setCapacity(size_t size) { m_capacity = size; }
void enqueue(const _Tp& item);
void enqueue(_Tp* item);
#if __cplusplus >= 201103L
// rvalue reference parameter: -std=c++11
void enqueue(_Tp&& item);
#endif
const _Tp& dequeue();
bool isEmpty() const { return !m_size; }
void print() const;
private:
void popFront();
void copyFrom(const StaticQueue& rhs);
void moveFrom(StaticQueue& rhs);
void destroy();
size_t m_size; // Current queue size
size_t m_capacity; // Maximum queue size
_Tp* m_dequeue_item; // Storage for a dequeued item
_Tp_Data* m_data; // Queue container for storing FIFO data
};
template<typename _Tp>
inline void StaticQueue<_Tp>::enqueue(const _Tp& item)
{
m_data->push_back(new _Tp(item));
if(++m_size > m_capacity) {
popFront();
m_size = m_capacity;
}
}
template<typename _Tp>
inline void StaticQueue<_Tp>::enqueue(_Tp* item)
{
m_data->push_back(item);
if(++m_size > m_capacity) {
popFront();
m_size = m_capacity;
}
}
#if __cplusplus >= 201103L
template<typename _Tp>
inline void StaticQueue<_Tp>::enqueue(_Tp&& item)
{
m_data->push_back(new _Tp(item));
if(++m_size > m_capacity) {
popFront();
m_size = m_capacity;
}
}
#endif
template<typename _Tp>
inline const _Tp& StaticQueue<_Tp>::dequeue()
{
// What if undeflow condition(m_size==0)?
if(m_size) {
*m_dequeue_item = *m_data->front();
popFront();
--m_size;
}
return *m_dequeue_item;
}
template<typename _Tp>
inline void StaticQueue<_Tp>::print() const
{
std::cout << "\nQueue size/capacity: " << size() << "/" << capacity() << std::endl;
if(!isEmpty()) {
int c = 0;
for(const_iterator i=m_data->begin(); i != m_data->end(); ++i) {
std::cout << c++ << ": ";
(*i)->print();
}
}
}
template<typename _Tp>
inline void StaticQueue<_Tp>::popFront()
{
delete m_data->front();
m_data->pop_front();
}
template<typename _Tp>
inline void StaticQueue<_Tp>::copyFrom(const StaticQueue<_Tp>& rhs)
{
m_size = rhs.m_size;
m_capacity = rhs.m_capacity;
m_dequeue_item = new _Tp(*rhs.m_dequeue_item);
m_data = new _Tp_Data;
for(size_t i=0; i < rhs.m_size; ++i) {
_Tp* item = new _Tp(rhs[i]);
m_data->push_back(item);
}
}
template<typename _Tp>
inline void StaticQueue<_Tp>::moveFrom(StaticQueue<_Tp>& rhs)
{
m_size = rhs.m_size;
m_capacity = rhs.m_capacity;
m_dequeue_item = rhs.m_dequeue_item;
m_data = rhs.m_data;
rhs.m_size = 0;
rhs.m_capacity = 0;
rhs.m_dequeue_item = 0;
rhs.m_data = 0;
}
template<typename _Tp>
inline void StaticQueue<_Tp>::destroy()
{
if(m_dequeue_item) delete m_dequeue_item;
m_dequeue_item = 0;
if(!isEmpty()) {
for(iterator i=m_data->begin(); i != m_data->end();) {
delete *i;
i = m_data->erase(i);
}
}
if(m_data) delete m_data;
m_data = 0;
}
참고 사항
구글 blogger에 소스 코드 삽입시 Syntax Highlighter를 사용하는 방법은 아래의 사이트 참조.
http://oneqonea.blogspot.kr/2012/04/how-do-i-add-syntax-highlighting-to-my.html
댓글 없음:
댓글 쓰기