Skip to content

Instantly share code, notes, and snippets.

@zavorka
Created September 14, 2016 15:30
Show Gist options
  • Save zavorka/190d660ba8c38196effe9efed74a34b5 to your computer and use it in GitHub Desktop.
Save zavorka/190d660ba8c38196effe9efed74a34b5 to your computer and use it in GitHub Desktop.
// Copyright (c) 2016 Roman Beránek. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <algorithm>
#include <type_traits>
#include <utility>
namespace re {
namespace lib {
template <typename C>
class Ring
{
public:
using value_type = typename C::value_type;
using pointer = value_type*;
using reference = value_type&;
using const_reference = value_type const&;
using universal_reference = value_type&&;
using size_type = typename C::size_type;
using difference_type = typename C::difference_type;
using index_type = difference_type;
using iterator = typename C::iterator;
using const_iterator = typename C::const_iterator;
using reverse_iterator = typename C::reverse_iterator;
using const_reverse_iterator = typename C::const_reverse_iterator;
constexpr Ring()
noexcept(std::is_nothrow_default_constructible<C>::value)
{
}
constexpr Ring(Ring const& ring)
noexcept(std::is_nothrow_copy_constructible<C>::value) :
c(ring.c)
{
}
constexpr Ring(Ring&& ring)
noexcept(std::is_nothrow_move_constructible<C>::value) :
c(std::move(ring.c))
{
}
constexpr Ring(C const& rhs)
noexcept(std::is_nothrow_copy_constructible<C>::value) :
c(rhs)
{
}
constexpr Ring(C&& rhs)
noexcept(std::is_nothrow_move_constructible<C>::value) :
c(std::move(rhs))
{
}
constexpr Ring& operator=(Ring const& rhs)
noexcept(std::is_nothrow_copy_assignable<C>::value) {
c = rhs.c;
return *this;
}
constexpr Ring& operator=(Ring&& rhs)
noexcept(std::is_nothrow_move_assignable<C>::value) {
c = std::move(rhs.c);
return *this;
}
constexpr Ring& operator=(C const& rhs)
noexcept(std::is_nothrow_copy_assignable<C>::value) {
c = rhs;
return *this;
}
constexpr Ring& operator=(C&& rhs)
noexcept(std::is_nothrow_move_assignable<C>::value) {
c = std::move(rhs);
return *this;
}
template <typename T, typename std::enable_if_t<std::is_assignable<C, T>::value>>
constexpr Ring& operator=(T&& t)
noexcept(std::is_nothrow_assignable<C, T>::value) {
c = std::forward<T>(t);
return *this;
}
void swap(Ring& rhs)
noexcept (c.swap(rhs.c)) {
c.swap(rhs.c);
}
void swap(C& rhs)
noexcept (c.swap(rhs)) {
c.swap(rhs);
}
constexpr size_type size() const noexcept { return c.size(); }
constexpr size_type max_size() const noexcept { return size(); }
constexpr bool empty() const noexcept { return c.empty(); }
constexpr pointer data() const noexcept { return c.data(); }
constexpr void fill(const_reference value)
noexcept(std::is_nothrow_copy_constructible<value_type>::value) {
std::fill(begin(), end(), value);
}
constexpr reference operator[](index_type i) { return c[i]; }
constexpr const_reference operator[](index_type i) const noexcept { return c[i]; }
constexpr reference at() { return c.back(); }
constexpr const_reference at() const { return c.back(); }
constexpr reference front() noexcept { return c.front(); }
constexpr const_reference front() const noexcept { return c.front(); }
constexpr reference back() noexcept { return c.back(); }
constexpr const_reference back() const noexcept { return c.back(); }
constexpr iterator begin() const noexcept { return c.begin(); }
constexpr iterator end() noexcept { return c.end(); }
constexpr const_iterator begin() noexcept { return c.begin(); }
constexpr const_iterator end() const noexcept { return c.end(); }
constexpr const_iterator cbegin() const noexcept { return c.cbegin(); }
constexpr const_iterator cend() const noexcept { return c.cend(); }
constexpr reverse_iterator rbegin() noexcept { return c.rbegin(); }
constexpr reverse_iterator rend() noexcept { return c.rend(); }
constexpr const_reverse_iterator rbegin() const noexcept { return c.rbegin(); }
constexpr const_reverse_iterator rend() const noexcept { return c.rend(); }
constexpr const_reverse_iterator crbegin() const noexcept { return c.crbegin(); }
constexpr const_reverse_iterator crend() const noexcept { return c.crend(); }
constexpr void push_back(const_reference value)
noexcept(std::is_nothrow_copy_constructible<value_type>::value) {
auto value_copy{value};
emplace_back(std::move(value_copy));
}
constexpr void push_back(universal_reference value)
noexcept(std::is_nothrow_move_assignable<value_type>::value) {
emplace_back(std::move(value));
}
template <typename... From>
constexpr reference emplace_back(From&&... from)
noexcept(std::is_nothrow_constructible<value_type, From...>::value
&& std::is_nothrow_move_assignable<value_type>::value)
{
front() = value_type(std::forward<From>(from)...);
std::rotate(begin(), begin() + 1, end());
return back();
}
constexpr void push_front(const_reference value)
noexcept(std::is_nothrow_copy_constructible<value_type>::value) {
auto value_copy{value};
emplace_front(std::move(value_copy));
}
constexpr void push_front(universal_reference value)
noexcept(std::is_nothrow_move_assignable<value_type>::value) {
emplace_front(std::move(value));
}
template <typename... From>
constexpr reference emplace_front(From&&... from)
noexcept(std::is_nothrow_constructible<value_type, From...>::value
&& std::is_nothrow_move_assignable<value_type>::value) {
back() = value_type(std::forward<From>(from)...);
std::rotate(begin(), end() - 1, end());
return front();
}
constexpr void insert(const_iterator pos, size_type n, value_type value)
noexcept(std::is_nothrow_copy_constructible<value_type>::value
&& std::is_nothrow_move_assignable<value_type>::value) {
difference_type d = std::distance(cbegin(), pos);
d = std::min(d, static_cast<difference_type>(n));
while (d-- > 0) {
insert(pos, value);
}
}
template <typename InputIt>
constexpr void insert(const_iterator pos, InputIt first, InputIt last)
noexcept(std::is_nothrow_copy_constructible<value_type>::value
&& std::is_nothrow_move_assignable<value_type>::value) {
while (first != last) {
insert(pos, *(first++));
}
}
constexpr iterator insert(const_iterator pos, const_reference value)
noexcept(std::is_nothrow_copy_constructible<value_type>::value
&& std::is_nothrow_move_assignable<value_type>::value) {
auto value_copy{value};
return emplace(pos, std::move(value_copy));
}
constexpr iterator insert(const_iterator pos, universal_reference value)
noexcept(std::is_nothrow_move_assignable<value_type>::value) {
return emplace(pos, std::move(value));
}
constexpr void rinsert(const_iterator pos, size_type n, value_type value)
noexcept(std::is_nothrow_copy_constructible<value_type>::value
&& std::is_nothrow_move_assignable<value_type>::value) {
difference_type d = std::distance(pos, cend());
d = std::min(d, static_cast<difference_type>(n));
while (d-- > 0) {
rinsert(pos, value);
}
}
template <typename InputIt>
constexpr void rinsert(const_iterator pos, InputIt first, InputIt last)
noexcept(std::is_nothrow_copy_constructible<value_type>::value
&& std::is_nothrow_move_assignable<value_type>::value) {
while (first != last) {
rinsert(pos, *(first++));
}
}
constexpr iterator rinsert(const_iterator pos, const_reference value)
noexcept(std::is_nothrow_copy_constructible<value_type>::value
&& std::is_nothrow_move_assignable<value_type>::value) {
auto value_copy{value};
return remplace(pos, std::move(value_copy));
}
constexpr iterator rinsert(const_iterator pos, universal_reference value)
noexcept(std::is_nothrow_move_assignable<value_type>::value) {
return remplace(pos, std::move(value));
}
template <typename... From>
constexpr iterator emplace(const_iterator pos, From&&... from)
noexcept(std::is_nothrow_constructible<value_type, From...>::value
&& std::is_nothrow_move_assignable<value_type>::value)
{
auto d = std::distance(cbegin(), pos);
if (d == 0) {
return begin();
}
front() = value_type(std::forward<From>(from)...);
if (d == 1) {
return begin();
}
auto last = begin() + d;
std::rotate(begin(), begin() + 1, last);
return last;
}
template <typename... From>
constexpr iterator remplace(const_iterator pos, From&&... from)
noexcept(std::is_nothrow_constructible<value_type, From...>::value
&& std::is_nothrow_move_assignable<value_type>::value)
{
auto d = std::distance(pos, end());
if (d == 0) {
return end();
}
back() = value_type(std::forward<From>(from)...);
if (d == 1) {
return end() - 1;
}
auto first = end() - d;
std::rotate(first, end() - 1, end()) - 1;
return first;
}
private:
C c;
};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment