#ifndef INCLUDED_CIRQUE_H_ #define INCLUDED_CIRQUE_H_ #include #include #include template class CirQue { //DATA size_t d_size; size_t d_maxSize; Data *d_data; Data *d_front; Data *d_back; //= public: //TYPEDEFS using value_type = Data; using const_reference = const &value_type; //= //EXCEPTION enum Exception { EMPTY, FULL }; //= explicit CirQue(size_t maxSize = 0); CirQue(CirQue const &other); CirQue(CirQue &&tmp); template explicit CirQue(Data const (&arr)[Size]); explicit CirQue(Data const *data, size_t size); ~CirQue(); CirQue &operator=(CirQue const &other); CirQue &operator=(CirQue &&tmp); Data &back(); Data &front(); bool empty() const; bool full() const; size_t maxSize() const; size_t size() const; void pop_front(); void push_back(Data const &object); void swap(CirQue &other); private: Data *inc(Data *ptr); }; //CIRQUE template CirQue::CirQue(size_t maxSize) : d_size(0), d_maxSize(maxSize), d_data( maxSize == 0 ? 0 : static_cast( operator new(maxSize * sizeof(Data))) ), d_front(d_data), d_back(d_data) {} //= //COPYCONS template CirQue::CirQue(CirQue const &other) : d_size(other.d_size), d_maxSize(other.d_maxSize), d_data( d_maxSize == 0 ? 0 : static_cast( operator new(d_maxSize * sizeof(Data))) ), d_front(d_data + (other.d_front - other.d_data)) { Data const *src = other.d_front; d_back = d_front; for (size_t count = 0; count != d_size; ++count) { new(d_back) Data(*src); d_back = inc(d_back); if (++src == other.d_data + d_maxSize) src = other.d_data; } } //= //MOVECONS template CirQue::CirQue(CirQue &&tmp) : d_data(0) { swap(tmp); } //= //MEMBER template template CirQue::CirQue(Data const (&arr)[Size]) : d_size(0), d_maxSize(Size), d_data(static_cast(operator new(sizeof(arr)))), d_front(d_data), d_back(d_data) { std::copy(arr, arr + Size, std::back_inserter(*this)); } //= //DESTRUCTOR template CirQue::~CirQue() { if (d_data == 0) return; for (; d_size--; ) { d_front->~Data(); d_front = inc(d_front); } operator delete(d_data); } //= //COPYASSIGN template CirQue &CirQue::operator=(CirQue const &rhs) { CirQue tmp(rhs); swap(tmp); return *this; } //= //MOVEASSIGN template inline CirQue &CirQue::operator=(CirQue &&tmp) { swap(tmp); return *this; } //= //SWAP template void CirQue::swap(CirQue &other) { static size_t const size = sizeof(CirQue); char tmp[size]; memcpy(tmp, &other, size); memcpy(reinterpret_cast(&other), this, size); memcpy(reinterpret_cast(this), tmp, size); } //= //POPFRONT template void CirQue::pop_front() { if (d_size == 0) throw EMPTY; d_front->~Data(); d_front = inc(d_front); --d_size; } //= //PUSHBACK template void CirQue::push_back(Data const &object) { if (d_size == d_maxSize) throw FULL; new (d_back) Data(object); d_back = inc(d_back); ++d_size; } //= //BACK template inline Data &CirQue::back() { return d_back == d_data ? d_data[d_maxSize - 1] : d_back[-1]; } //= //FRONT template inline Data &CirQue::front() { return *d_front; } //= //EMPTY template inline bool CirQue::empty() const { return d_size == 0; } //= //FULL template inline bool CirQue::full() const { return d_size == d_maxSize; } //= //SIZE template inline size_t CirQue::size() const { return d_size; } //= //MAXSIZE template inline size_t CirQue::maxSize() const { return d_maxSize; } //= //INC template Data *CirQue::inc(Data *ptr) { ++ptr; return ptr == d_data + d_maxSize ? d_data : ptr; } //= #endif