Created
September 27, 2016 19:10
-
-
Save dgodfrey206/be9dfa6c42bc9548c1bb4e5fdbba7a4a to your computer and use it in GitHub Desktop.
Test
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdexcept> | |
#include <iostream> | |
#include <memory> | |
#include <cstring> | |
#include <cmath> | |
using namespace std; | |
template<class T> | |
class RingBuffer; | |
template<class V>struct X; | |
template<class T> | |
struct wrap_iterator { | |
using iterator=wrap_iterator; | |
template<class I>struct range_t{I b,e;}; | |
range_t<size_t> r; | |
T& obj; | |
auto& operator*(){return obj.buffer[r.b];} | |
auto const& operator*()const{return obj.buffer[r.b];} | |
iterator operator+(int i) const { | |
iterator copy(*this); | |
return (copy.r.b + 1) % copy.r.e; | |
} | |
iterator operator-(int i) const { | |
iterator copy(*this); | |
if (copy.r.b == 0) | |
copy.r.b = copy.r.e - 1; | |
else | |
copy.r.b--; | |
return copy; | |
} | |
iterator& operator++() { | |
r.b = (r.b + 1) % r.e; | |
return *this; | |
} | |
iterator operator++(int) { | |
iterator copy(*this); | |
operator++(); | |
return copy; | |
} | |
friend bool operator==(iterator const&lhs,iterator const&rhs){ | |
return lhs.r.b==rhs.r.b; | |
} | |
friend bool operator!=(iterator const&lhs,iterator const&rhs){ | |
return !(lhs==rhs); | |
} | |
}; | |
template<class I,class T> | |
auto make_iterator(I beg, I end,T&& obj) { | |
using iterator=::wrap_iterator<remove_reference_t<T>>; | |
return iterator{typename iterator::template range_t<I> | |
{move(beg), | |
move(end)}, | |
obj}; | |
} | |
template<class T> | |
class RingBuffer { | |
friend struct wrap_iterator<RingBuffer<T>>; | |
friend struct wrap_iterator<RingBuffer<T> const>; | |
friend struct wrap_iterator<RingBuffer<T> const&>; | |
public: | |
RingBuffer() = delete; | |
RingBuffer(size_t); | |
RingBuffer(size_t, T const&); | |
// modifiers | |
T get() const; | |
void push_back(T const&); | |
void pop_back(); | |
void pop_front(); | |
// access | |
T& front(); | |
T const& front() const; | |
T& back(); | |
T const& back() const; | |
// iterators | |
auto begin(); | |
auto const begin() const; | |
auto end(); | |
auto const end() const; | |
// size | |
size_t size() const; | |
bool empty() const; | |
bool full() const; | |
private: | |
void push_back(T const&, true_type); | |
void push_back(T const&, false_type); | |
void set_next_write_position() const; | |
void set_next_read_position() const; | |
private: | |
unique_ptr<T[]> buffer = nullptr; | |
mutable size_t read, write, length, capacity = 0; | |
}; | |
template<class T> | |
RingBuffer<T>::RingBuffer(size_t capacity) | |
: buffer(make_unique<T[]>(capacity+1)) | |
, read(0) | |
, write(0) | |
, length(0) | |
, capacity(capacity+1) | |
{} | |
template<class T> | |
RingBuffer<T>::RingBuffer(size_t capacity, T const& value) | |
: RingBuffer(capacity) | |
{ | |
for (int i = 0; i < capacity; ++i) | |
push_back(value); | |
} | |
template<class T> | |
void RingBuffer<T>::push_back(T const& value) { | |
if (!full()) { | |
push_back(value, is_trivially_copyable<T>{}); | |
write = (write + 1) % capacity; | |
++length; | |
} | |
} | |
template<class T> | |
void RingBuffer<T>::push_back(T const& value, true_type) { | |
memcpy(reinterpret_cast<void*>(&buffer[write]), reinterpret_cast<void*>(const_cast<T*>(&value)), sizeof(value)); | |
} | |
template<class T> | |
void RingBuffer<T>::push_back(T const& value, false_type) { | |
buffer[write] = value; | |
} | |
template<class T> | |
T RingBuffer<T>::get() const { | |
if (!empty()) { | |
T tmp = buffer[read]; | |
read = (read + 1) % capacity; | |
--length; | |
return tmp; | |
} | |
throw logic_error("empty buffer"); | |
} | |
template<class T> | |
void RingBuffer<T>::pop_front() { | |
if (!empty()) { | |
read = (read + 1) % capacity; | |
--length; | |
} | |
else { | |
throw logic_error("empty"); | |
} | |
} | |
template<class T> | |
void RingBuffer<T>::pop_back() { | |
if (!empty()) { | |
if (--write < 0) write = length - 1; | |
--length; | |
} | |
throw logic_error("empty"); | |
} | |
template<class T> | |
auto const RingBuffer<T>::begin() const { | |
return make_iterator(read,size(),*this); | |
} | |
template<class T> | |
auto RingBuffer<T>::begin() { | |
return make_iterator(read,size(),*this); | |
} | |
template<class T> | |
auto const RingBuffer<T>::end() const { | |
return make_iterator(write,size(),*this); | |
} | |
template<class T> | |
auto RingBuffer<T>::end() { | |
return make_iterator(write,size(),*this); | |
} | |
template<class T> | |
T const& RingBuffer<T>::front() const { | |
return *begin(); | |
} | |
template<class T> | |
T& RingBuffer<T>::front() { | |
return *begin(); | |
} | |
template<class T> | |
T& RingBuffer<T>::back() { | |
if (size() <= 1) | |
return *begin(); | |
return *(end() - 1); | |
} | |
template<class T> | |
T const& RingBuffer<T>::back() const { | |
return const_cast<RingBuffer<T>&>(*this).back(); | |
} | |
template<class T> | |
size_t RingBuffer<T>::size() const { | |
return length; | |
} | |
template<class T> | |
bool RingBuffer<T>::full() const { | |
return read == (write + 1) % capacity; | |
} | |
template<class T> | |
bool RingBuffer<T>::empty() const { | |
return length == 0; | |
} | |
void print(RingBuffer<int>const&rb){ | |
for(auto x:rb)cout<<3<<' '; | |
cout<<'\n'; | |
} | |
template<class T> | |
void f(T& x){ | |
cout<<x.r.b<<' '<<*x<<'\n'; | |
x++; | |
} | |
int main() { | |
RingBuffer<int> rb(10); | |
int i; | |
for(i=1;i<=10;++i)rb.push_back(i); | |
//rb.pop_front(); | |
auto it=rb.begin(); | |
f(it);f(it);f(it);f(it);f(it);f(it);f(it);f(it);f(it);f(it);f(it); | |
cout<<rb.end().r.b<<' '<<it.r.b; | |
//print(rb); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment